// These will all be prefs eventually
//var readLightColor = "#ddeeff";
//var readDarkColor = "#bbccdd";
//var readWithNewLightColor = "#e1f1e1";
//var readWithNewDarkColor = "#cfdfcf";
//var unreadLightColor = "#f1f1f1";
//var unreadDarkColor = "#dfdfdf";

//var postedInThreadReColor = "#fcfd99";

var SALR_CURRENT_VERSION = "1.15.1918";
var needToShowChangeLog = false;
var upgradeFromVersion = null;

var THREAD_ICON_COUNT = 2;

//var expireMinAge = 7;  // how many days old must a thread entry be before it's deleted?

// WARNING WARNING WARNING WARNING
// Changing the following value, or any of the code that enforces the delay,
// you may get banned from the forums. This delay is here at radium's command!
var minMyThreadRefreshInterval = 60;

var initialDocShellPrepared = false;
var thisWindowPageTimers = new Array();

//////////////////////////////////////////////

var persistObject = null;

function GetUserProfileDirectory(fn) {
   const DIR_SERVICE = new Components.Constructor("@mozilla.org/file/directory_service;1", "nsIProperties");
   var path;
   try {
      path = (new DIR_SERVICE()).get("ProfD", Components.interfaces.nsIFile).path;
   } catch (e) {
   }
   if (path) {
      if (fn) {
         if (path.search(/\\/) != -1) {
            path = path + "\\";
         } else {
            path = path + "/";
         }
         path = path + fn;
      }
      return path;
   } else {
      return null;
   }
}

function ReadFile(fn) {
   try {
      netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
   } catch (e) {
      return null;
   }
   var file = Components.classes["@mozilla.org/file/local;1"]
         .createInstance(Components.interfaces.nsILocalFile);
   file.initWithPath(fn);
   if (file.exists() == false) {
      return "";
   }
   var is = Components.classes["@mozilla.org/network/file-input-stream;1"]
         .createInstance(Components.interfaces.nsIFileInputStream);
   is.init(file, 0x01, 00004, null);
   var sis = Components.classes["@mozilla.org/scriptableinputstream;1"]
         .createInstance(Components.interfaces.nsIScriptableInputStream);
   sis.init(is);
   return sis.read( sis.available() );
}

function SaveFile(fn, fdata) {
   try {
      netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
   } catch (e) {
      alert("The SALastRead failed to save settings because permission was denied.");
      return null;
   }
   var file = Components.classes["@mozilla.org/file/local;1"]
         .createInstance(Components.interfaces.nsILocalFile);
   file.initWithPath(fn);
   if ( file.exists() == false ) {
      file.create(Components.interfaces.nsIFile.NORMAL_FILE_TYPE, 420);
      alert("The SALastRead extension is initializing a new settings file. You should only see this once, after you first install the extension.");
   }
   var outputStream = Components.classes["@mozilla.org/network/file-output-stream;1"]
         .createInstance(Components.interfaces.nsIFileOutputStream);
   outputStream.init(file, 0x04 | 0x08 | 0x20, 420, 0);
   var result = outputStream.write( fdata, fdata.length );
   outputStream.close();
}

function StripSpaces(str) {
   while (str.substring(0,1) > '~' || str.substring(0,1) < '!') str = str.substring(1);
   while (str.substring(str.length-1, str.length) == ' ') str = str.substring(0, str.length-1);
   return str;
}

function GetCurrentLPDateTime() {
   var now = new Date();
   var day = "00" + now.getDate();
   var month = "00" + (now.getMonth()+1);
   var year = "00" + (now.getYear()+1900);
   var hour = "00" + now.getHours();
   var minute = "00" + now.getMinutes();
   day = day.substring(day.length-2,day.length);
   month = month.substring(month.length-2,month.length);
   year = year.substring(year.length-4,year.length);
   hour = hour.substring(hour.length-2,hour.length);
   minute = minute.substring(minute.length-2,minute.length);
   return year + month + day + hour + minute;
}

function ConvertLPDateTimeToNum(lpdate, lptime) {
   // Jun 05, 2006    14:46
   // 012345678901    01234
   var monthstr = lpdate.substring(0,3);  // "Jun"
   var day = lpdate.substring(4,6);       // "05"
   var year = lpdate.substring(8,12);     // "2006"
   var hour = lptime.substring(0,2);      // "14"
   var minute = lptime.substring(3,6);    // "46"
   var month = "00";
   if (monthstr == "Jan") month = "01";
   if (monthstr == "Feb") month = "02";
   if (monthstr == "Mar") month = "03";
   if (monthstr == "Apr") month = "04";
   if (monthstr == "May") month = "05";
   if (monthstr == "Jun") month = "06";
   if (monthstr == "Jul") month = "07";
   if (monthstr == "Aug") month = "08";
   if (monthstr == "Sep") month = "09";
   if (monthstr == "Oct") month = "10";
   if (monthstr == "Nov") month = "11";
   if (monthstr == "Dec") month = "12";
   return year + month + day + hour + minute;
}

function SALRCachedThreadEntry(threadid) {
   this._xmlnode = selectSingleNode(persistObject.xmlDoc, persistObject.xmlDoc, "/salastread/thread[@id='"+threadid+"']");
   if ( !this._xmlnode ) {
      var newel = persistObject.xmlDoc.createElement("thread");
      newel.setAttribute("id", threadid);
      newel.setAttribute("lastpostdt", "0");
      newel.setAttribute("lastpostid", "0");
      this._needadd = true;
      //persistObject.xmlDoc.documentElement.insertBefore(newel, persistObject.xmlDoc.documentElement.firstChild);
      this._xmlnode = newel;
   }
   this._expireage = (new Date()).getTime();
}

SALRCachedThreadEntry.prototype = {
   _needadd: false,
   _xmlnode: null,
   _expireage: null,

   _frozen: false,
   _frozendt: false,
   _frozenid: false,
   _lastpostdt: null,
   _lastpostid: null,

   IsAged: function() {
      var now = (new Date()).getTime();
      return ( now >= this._expireage );
   },

   _setDelay: function() {
      this._expireage = (new Date()).getTime() + 5000;
   },

   renewDelay: function() {
      if ( this._frozen && !this.IsAged() ) {
         this._setDelay();
      }
   },

   getBypassAttribute: function(name) {
      return this._xmlnode.getAttribute(name);
   },

   getAttribute: function(name) {
      if ( this._frozen && name=="lastpostdt" && !this.IsAged() ) {
         return this._lastpostdt;
      }
      else if ( this._frozen && name=="lastpostid" && !this.IsAged() ) {
         return this._lastpostid;
      }
      else {
         return this._xmlnode.getAttribute(name);
      }
   },

   removeAttribute: function(name) {
      return this._xmlnode.removeAttribute(name);
   },

   setAttribute: function(name, value) {
      if ( !this._frozen ) {
         if ( name=="lastpostdt" && !this._frozendt ) {
            this._lastpostdt = this._xmlnode.getAttribute(name);
            this._frozendt = true;
         }
         if ( name=="lastpostid" && !this._frozenid ) {
            this._lastpostid = this._xmlnode.getAttribute(name);
            this._frozenid = true;
         }
         if ( this._frozendt && this._frozenid ) {
            this._frozen = true;
            this._setDelay();
            if (this._needadd) {
               persistObject.xmlDoc.documentElement.insertBefore(this._xmlnode, persistObject.xmlDoc.documentElement.firstChild);
               persistObject.xmlDoc.documentElement.insertBefore(persistObject.xmlDoc.createTextNode("\n"), persistObject.xmlDoc.documentElement.firstChild);
               this._needadd = false;
            }
         }
      }
      return this._xmlnode.setAttribute(name, value);
   },
};

//var cachedThreadEntryList = new Array();

function invalidateAgedCachedEntries() {
   var newList = new Array();
   for (var i=0; i<persistObject._cachedThreadEntryList.length; i++) {
      var thisEntry = persistObject._cachedThreadEntryList[i];
      if ( !thisEntry.IsAged() ) {
         newList.push(thisEntry);
      }
   }
   persistObject._cachedThreadEntryList = newList;
}

var cachedThreadEntry = null;

function slurpIntoThreadCache(threadid) {
   var needRead = false;
   if ( cachedThreadEntry ) {
      if ( cachedThreadEntry.getAttribute("id") != threadid ) {
         needRead = true;
      }
   } else {
      needRead = true;
   }
   if (needRead) {
      invalidateAgedCachedEntries();
      cachedThreadEntry = null;
      for (var i=0; i<persistObject._cachedThreadEntryList.length; i++) {
         if ( persistObject._cachedThreadEntryList[i].getAttribute("id")==threadid ) {
            cachedThreadEntry = persistObject._cachedThreadEntryList[i];
            cachedThreadEntry.setAttribute("lastviewdt", SALR_GetCurrentDT());
            return;
         }
      }
      if (!cachedThreadEntry) {
         cachedThreadEntry = new SALRCachedThreadEntry(threadid);
         persistObject._cachedThreadEntryList.push(cachedThreadEntry);
         //cachedThreadEntry = selectSingleNode(persistObject.xmlDoc, persistObject.xmlDoc, "/salastread/thread[@id='"+threadid+"']");
      }
   }
   cachedThreadEntry.setAttribute("lastviewdt", SALR_GetCurrentDT());
}

function SALR_GetCurrentDT() {
   return GetCurrentLPDateTime();
}

function invalidateThreadCache() {
   cachedThreadEntry = null;
}

function IsThreadIgnored(threadid) {
   slurpIntoThreadCache(threadid);
   if (cachedThreadEntry) {
      return (cachedThreadEntry.getAttribute("ignore")=="1");
   } else {
      return false;
   }
}

function IsLPDateTimeNew(bypassdelay, lpdtvalue, threadid, postid) {
   slurpIntoThreadCache(threadid);
   var lpidok = false;
   if (cachedThreadEntry) {
      if (bypassdelay) {
         lpidok = cachedThreadEntry.getBypassAttribute("lastpostid")>0;
      } else {
         lpidok = cachedThreadEntry.getAttribute("lastpostid")>0;
      }
   }
   //if (cachedThreadEntry && cachedThreadEntry.getAttribute("lastpostid")>0) {
   if (lpidok) {
      var lastdtval;
      var lpid;
      if ( bypassdelay ) {
         lastdtval = cachedThreadEntry.getBypassAttribute("lastpostdt");
         lpid = cachedThreadEntry.getBypassAttribute("lastpostid");
      } else {
         cachedThreadEntry.renewDelay();
         lastdtval = cachedThreadEntry.getAttribute("lastpostdt");
         lpid = cachedThreadEntry.getAttribute("lastpostid");
      }
      if ( lastdtval < lpdtvalue ) {
         return "readwithnew";
      } else {
         if ( !postid || postid <= lpid ) {
            return false;
         } else {
            return "readwithnew";
         }
      }
   } else {
      return "unread";
   }
}

function GetLastPostID(threadid) {
   slurpIntoThreadCache(threadid);
   return cachedThreadEntry.getAttribute("lastpostid");
}

function GetPostedInThread(threadid) {
   slurpIntoThreadCache(threadid);
   return cachedThreadEntry.getAttribute("posted");
}

function UpdateLPDateTime(updateTo, threadid, lastpostid) {
   slurpIntoThreadCache(threadid);
   if ( cachedThreadEntry ) {
      cachedThreadEntry.setAttribute("lastpostdt", updateTo);
      cachedThreadEntry.setAttribute("lastpostid", lastpostid);
   } else {
      alert("SALastRead: should never get here");
      var newel = persistObject.xmlDoc.createElement("thread");
      newel.setAttribute("id", threadid);
      newel.setAttribute("lastpostdt", updateTo);
      newel.setAttribute("lastpostid", lastpostid);
      persistObject.xmlDoc.documentElement.insertBefore(newel, persistObject.xmlDoc.documentElement.firstChild);
   }
   //persistObject.SaveXML();
   var threaddetails = new Array();
   threaddetails['id'] = threadid;
   threaddetails['lastpostdt'] = updateTo;
   threaddetails['lastpostid'] = lastpostid;
   persistObject.SavePostDataSQL(threaddetails);
}

function SALRHexToNumber(hex) {
   var res = 0;
   for (var i=0; i<hex.length; i++) {
      res = res * 16;
      switch (hex[i]) {
         case "0": res += 0; break;
         case "1": res += 1; break;
         case "2": res += 2; break;
         case "3": res += 3; break;
         case "4": res += 4; break;
         case "5": res += 5; break;
         case "6": res += 6; break;
         case "7": res += 7; break;
         case "8": res += 8; break;
         case "9": res += 9; break;
         case "a": case "A": res += 10; break;
         case "b": case "B": res += 11; break;
         case "c": case "C": res += 12; break;
         case "d": case "D": res += 13; break;
         case "e": case "E": res += 14; break;
         case "f": case "F": res += 15; break;
      }
   }
   return res;
}

function SALR_MakeShowThreadCSS() {
   var csstxt = "";
   csstxt += "table.salastread_seenpost.salastread_odd tr { background-color: "+persistObject.color_seenPostDark+" !important; }\n\n";
   csstxt += "table.salastread_seenpost.salastread_even tr { background-color: "+persistObject.color_seenPostLight+" !important; }\n\n";
   //csstxt += "table.salastread_unseenpost.salastread_odd tr { background-color: "+persistObject.color_unseenPostDark+" !important; }\n\n";
   //csstxt += "table.salastread_unseenpost.salastread_even tr { background-color: "+persistObject.color_unseenPostLight+" !important; }\n\n";
   if ( persistObject.toggle_hideTitle ) {
      csstxt += "dd.title * { display: none; }\n\n";
   } else if ( persistObject.toggle_resizeCustomTitleText ) {
      csstxt += "dd.title * { font-size: 8pt; }\n\n";
   }

   if ( persistObject.toggle_hideSignature)
   {
	   //So yeah firefox comes up with a pretty unique way of
	   //interpretting SA's invalid HTML......
      csstxt += ".signature + p + div { display: none; }\n\n"
   }

   // HEREHERE
   return csstxt;
}

function SALR_MakeForumDisplayCSS() {
   var sub = function(cls, isdark, basecolor, highlightcolor) {
      var res = "";
      if (isdark) {
         res += "tr."+cls+" td.icon,";
         res += "tr."+cls+" td.author,";
         res += "tr."+cls+" td.views,";
         res += "tr."+cls+" td.lastpost";
      } else {
         res += "tr."+cls+" td.title,";
         res += "tr."+cls+" td.replies,";
         res += "tr."+cls+" td.rating";
      }
      res += " { background-repeat: repeat-x !important; background-color: "+basecolor + " !important";
      if (highlightcolor && !persistObject.toggle_disableGradients) {
         res += "; background-image: url(x-salr-gradientpng:" +
                    SALRHexToNumber(highlightcolor.substring(1,3)) + "," +
                    SALRHexToNumber(highlightcolor.substring(3,5)) + "," +
                    SALRHexToNumber(highlightcolor.substring(5,7)) + "," +
                    "33) !important";
      }
      res += "; }\n\n";

      res += "tr.salastread_postedinthread td.replies { background-repeat: repeat-x !important; background-color: "+
                    persistObject.color_postedInThreadRe + " !important";
      if (persistObject.color_postedInThreadReHighlight && !persistObject.toggle_disableGradients) {
         var highlightcolor = persistObject.color_postedInThreadReHighlight;
         res += "; background-image: url(x-salr-gradientpng:" +
                    SALRHexToNumber(highlightcolor.substring(1,3)) + "," +
                    SALRHexToNumber(highlightcolor.substring(3,5)) + "," +
                    SALRHexToNumber(highlightcolor.substring(5,7)) + "," +
                    "33) !important";
      }
      res += "; }\n\n";

      return res;
   };

   var csstext = "";
   csstext += sub("salastread_readthread", true, persistObject.color_readDark, persistObject.color_readDarkHighlight);
   csstext += sub("salastread_readthread", false, persistObject.color_readLight, persistObject.color_readLightHighlight);
   csstext += sub("salastread_readwithnewthread", true, persistObject.color_readWithNewDark, persistObject.color_readWithNewDarkHighlight);
   csstext += sub("salastread_readwithnewthread", false, persistObject.color_readWithNewLight, persistObject.color_readWithNewLightHighlight);
   //csstext += sub("salastread_unreadthread", true, persistObject.color_unreadDark, persistObject.color_unreadDarkHighlight);
   //csstext += sub("salastread_unreadthread", false, persistObject.color_unreadLight, persistObject.color_unreadLightHighlight);
   csstext += "td.replies { white-space: nowrap; }\n\n";
   csstext += ".salastread_newreplycount { font-weight: normal !important; }\n\n";

   return csstext;
}

function changeBGColorsFromTo(doc, context, xpathbase, bgfrom, bgto, bgtohighlight) {
   var xarray = selectNodes(doc, context, xpathbase+"[@bgcolor='"+bgfrom+"']");
   for (var x=0; x<xarray.length; x++) {
      xarray[x].style.backgroundColor = bgto;
      if ( bgtohighlight && !persistObject.toggle_disableGradients ) {
         xarray[x].style.backgroundRepeat = "repeat-x";
         xarray[x].style.backgroundImage = "url(x-salr-gradientpng:"+
              SALRHexToNumber( bgtohighlight.substring(1,3) ) + "," +
              SALRHexToNumber( bgtohighlight.substring(3,5) ) + "," +
              SALRHexToNumber( bgtohighlight.substring(5,7) ) + "," +
               "33)";
      }
   }
   return xarray;
}

//function setSeenPostFYADColors(doc, context, xpathbase) {
//   if ( persistObject.toggle_dontHighlightPosts ) { return; }
//   changeBGColorsFromTo(doc, context, xpathbase, "#ffccff", persistObject.color_seenPostLightFYAD);
//   changeBGColorsFromTo(doc, context, xpathbase, "#ffcccc", persistObject.color_seenPostDarkFYAD);
//}

function setSeenPostColors(doc, context, xpathbase) {
   if ( persistObject.toggle_dontHighlightPosts ) { return; }
   //changeBGColorsFromTo(doc, context, xpathbase, "#f1f1f1", persistObject.color_seenPostLight);
   //changeBGColorsFromTo(doc, context, xpathbase, "#dfdfdf", persistObject.color_seenPostDark);
   context.className += " salastread_seenpost";
   context.nextSibling.className += " salastread_seenpostbar";
}

//function setUnseenPostFYADColors(doc, context, xpathbase) {
//   if ( persistObject.toggle_dontHighlightPosts ) { return; }
//   changeBGColorsFromTo(doc, context, xpathbase, "#ffccff", persistObject.color_unseenPostLightFYAD);
//   changeBGColorsFromTo(doc, context, xpathbase, "#ffcccc", persistObject.color_unseenPostDarkFYAD);
//}

function setUnseenPostColors(doc, context, xpathbase) {
   if ( persistObject.toggle_dontHighlightPosts ) { return; }
   //changeBGColorsFromTo(doc, context, xpathbase, "#f1f1f1", persistObject.color_unseenPostLight);
   //changeBGColorsFromTo(doc, context, xpathbase, "#dfdfdf", persistObject.color_unseenPostDark);
   context.className += " salastread_unseenpost";
   context.nextSibling.className += " salastread_unseenpostbar";
}

function setReadColors(doc, context, xpathbase) {
   if ( persistObject.toggle_dontHighlightThreads ) { return; }
   var res = new Array(2);
   var r0 = changeBGColorsFromTo(doc, context, xpathbase, "#ffccff",
      persistObject.color_readLight, persistObject.color_readLightHighlight);
   var r1 = changeBGColorsFromTo(doc, context, xpathbase, "#ffcccc",
      persistObject.color_readDark, persistObject.color_readDarkHighlight);
   res[0] = changeBGColorsFromTo(doc, context, xpathbase, "#f1f1f1",
      persistObject.color_readLight, persistObject.color_readLightHighlight);
   res[1] = changeBGColorsFromTo(doc, context, xpathbase, "#dfdfdf",
      persistObject.color_readDark, persistObject.color_readDarkHighlight);
   for (var x=0; x<r0.length; x++) { res[0].push(r0[x]); }
   for (var y=0; y<r1.length; y++) { res[1].push(r1[y]); }
   return res;
}

function setReadWithNewColors(doc, context, xpathbase) {
   if ( persistObject.toggle_dontHighlightThreads ) { return; }
   var res = new Array(2);
   var r0 = changeBGColorsFromTo(doc, context, xpathbase, "#ffccff",
      persistObject.color_readWithNewLight, persistObject.color_readWithNewLightHighlight);
   var r1 = changeBGColorsFromTo(doc, context, xpathbase, "#ffcccc",
      persistObject.color_readWithNewDark, persistObject.color_readWithNewDarkHighlight);
   res[0] = changeBGColorsFromTo(doc, context, xpathbase, "#f1f1f1",
      persistObject.color_readWithNewLight, persistObject.color_readWithNewLightHighlight);
   res[1] = changeBGColorsFromTo(doc, context, xpathbase, "#dfdfdf",
      persistObject.color_readWithNewDark, persistObject.color_readWithNewDarkHighlight);
   for (var x=0; x<r0.length; x++) { res[0].push(r0[x]); }
   for (var y=0; y<r1.length; y++) { res[1].push(r1[y]); }
   return res;
}

function setUnreadColors(doc, context, xpathbase) {
   if ( persistObject.toggle_dontHighlightThreads ) { return; }
   var res = new Array(2);
   res[0] = changeBGColorsFromTo(doc, context, xpathbase, "#f1f1f1",
      persistObject.color_unreadLight, persistObject.color_unreadLightHighlight);
   res[1] = changeBGColorsFromTo(doc, context, xpathbase, "#dfdfdf",
      persistObject.color_unreadDark, persistObject.color_unreadDarkHighlight);
   return res;
}

function setUnreadFYADColors(doc, context, xpathbase) {
   if ( persistObject.toggle_dontHighlightThreads ) { return; }
   var res = new Array(2);
   res[0] = changeBGColorsFromTo(doc, context, xpathbase, "#ffccff",
      persistObject.color_unreadLightFYAD, persistObject.color_unreadLightFYADHighlight);
   res[1] = changeBGColorsFromTo(doc, context, xpathbase, "#ffcccc",
      persistObject.color_unreadDarkFYAD, persistObject.color_unreadDarkFYADHighlight);
   return res;
}

function resetUnreadColors(unvisitDecolors) {
   if ( persistObject.toggle_dontHighlightThreads ) { return; }
   for (var i=0; i<unvisitDecolors[0].length; i++) {
      unvisitDecolors[0][i].style.backgroundColor = persistObject.color_unreadLight;
      unvisitDecolors[0][i].style.backgroundImage = "";
   }
   for (var j=0; j<unvisitDecolors[1].length; j++) {
      unvisitDecolors[1][j].style.backgroundColor = persistObject.color_unreadDark;
      unvisitDecolors[1][j].style.backgroundImage = "";
   }
}

function SAmenuitemCommand2(event,el,etype) {
   var target = "none";
   if ( etype=="command" ) {
      target = "current";
   }
   if ( etype=="click" ) {
      if ( event.button == 2 || event.button == 1 ) {
         target = "newtab";
      }
   }

   if (target != "none") {
      SAmenuitemGoto(event,"http://forums.somethingawful.com/forumdisplay.php?s=&forumid="+el.getAttribute("forumnum"),target);
   }
}

function SAmenuitemCommandGoToLastPost(event, el, etype, threadid) {
   slurpIntoThreadCache(threadid);
   if (cachedThreadEntry) {
      var postid = cachedThreadEntry.getAttribute("lastpostid");
      SAmenuitemCommandURL2(event, "http://forums.somethingawful.com/showthread.php?s=&postid="+postid+"#post"+postid, etype);
   }
}

function SAmenuitemCommandURL2(event,el,etype) {
   var target = "none";
   if ( etype=="command" ) {
      target = "current";
   }
   if ( etype=="click" ) {
      if ( event.button == 2 || event.button == 1 ) {
         target = "newtab";
      }
   }

   var targeturl = "";
   if ( typeof(el) == "string" ) {
      targeturl = el;
   } else {
      targeturl = el.getAttribute("targeturl");
   }

   if (target != "none") {
      SAmenuitemGoto(event,targeturl,target);
   }
}

function SAmenuitemGoto(event,url,target) {
   if (target=="newtab") {
      getBrowser().addTab(url);
   }
   else if (target=="current") {
      loadURI(url);
   }
}

function grabForumList(e, selectnode) {
   var doc = e.originalTarget;
   var optionlist = selectNodes(doc, selectnode, "OPTION");
   var oDomParser = new DOMParser();
   var forumsDoc = oDomParser.parseFromString("<?xml version=\"1.0\"?>\n<forumlist></forumlist>", "text/xml");
   var targetEl = forumsDoc.documentElement;
   var oldForumXml = persistObject.forumListXml;
   for (var i=0; i<optionlist.length; i++) {
      var thisopt = optionlist[i];
      var thisopttext = thisopt.firstChild.nodeValue;
      if ( thisopttext.substring(0,2)=="--" && thisopt.getAttribute("value")!="-1" ) {
         var fel = forumsDoc.createElement("forum");
         var myid = thisopt.getAttribute("value");
         fel.setAttribute("id", myid);

         // Carry over sticky attributes
         if ( oldForumXml ) {
            var oldEl = selectSingleNode(oldForumXml, oldForumXml, "//forum[@id='"+myid+"']");
            if (oldEl) {
               if ( oldEl.hasAttribute("mods") ) {
                  fel.setAttribute("mods", oldEl.getAttribute("mods"));
               }
               if ( oldEl.hasAttribute("modnames") ) {
                  fel.setAttribute("modnames", oldEl.getAttribute("modnames"));
               }
            }
         }

         var catname = "sub";
         var xtext = thisopttext.substring(2);
         while ( xtext.substring(0,2)=="--" ) {
             catname += "-sub";
             xtext = xtext.substring(2);
         }
         xtext = xtext.substring(1);
         fel.setAttribute("name", xtext);
         fel.setAttribute("cat", catname);

//         if (thisopttext.substring(0,5)=="---- " && thisopt.getAttribute("value")!="-1" ) {
//            fel.setAttribute("name", "     " + thisopttext.substring(5));
//            fel.setAttribute("cat","sub-sub");
//         } else {
//            fel.setAttribute("name", thisopttext.substring(3));
//            fel.setAttribute("cat","sub");
//         }
         targetEl.appendChild(fel);
         targetEl.insertBefore(forumsDoc.createTextNode("\n"), fel);
      } else if (thisopt.getAttribute("value")!="-1" ) {
         var fel;
         if ( thisopt.getAttribute("value").match(/\D/) ) {
            fel = forumsDoc.createElement("util");
         } else {
            fel = forumsDoc.createElement("cat");
            targetEl = fel;
         }
         if(thisopttext.substring(0,1)  == " ") {
            fel.setAttribute("name", thisopttext.substring(1));
         } else {
            fel.setAttribute("name", thisopttext);
         }
         fel.setAttribute("id", thisopt.getAttribute("value"));
         forumsDoc.documentElement.appendChild(fel);
         forumsDoc.documentElement.insertBefore(forumsDoc.createTextNode("\n"), fel);
      }
   }
   persistObject.forumListXml = forumsDoc;
   if ( persistObject.toggle_showSAForumMenu ) {
      buildSAForumMenu();
   }
}

function populateForumMenuFrom(nested_menus,target,src,pinnedForumNumbers,pinnedForumElements) {
   var wasutil = 0;
   for (var i=0; i<src.childNodes.length; i++) {
      var thisforum = src.childNodes[i];
      if (thisforum.nodeName=="util") {
         wasutil = 1;
      }
      else if (wasutil && thisforum.nodeType == 1) {
         if (nested_menus) {
            target.appendChild(document.createElement("menuseparator"));
         }
         wasutil = 0;
      }
      if (thisforum.nodeName=="cat") {
         if (!nested_menus) {
            target.appendChild(document.createElement("menuseparator"));
            populateForumMenuFrom(nested_menus,target,thisforum,pinnedForumNumbers,pinnedForumElements);
         } else {
            var submenu = document.createElement("menu");
            submenu.setAttribute("label", thisforum.getAttribute("name"));
            var submenupopup = document.createElement("menupopup");
            if ( persistObject.toggle_useSAForumMenuBackground ) {
               submenupopup.setAttribute("class", "lastread_menu");
            }
            submenu.appendChild(submenupopup);
            populateForumMenuFrom(nested_menus,submenupopup,thisforum,pinnedForumNumbers,pinnedForumElements);
            target.appendChild(submenu);
         }
      }
      else if (thisforum.nodeName=="forum"||thisforum.nodeName=="util") {
         var menuel = document.createElement("menuitem");
         menuel.setAttribute("label", thisforum.getAttribute("name"));
         menuel.setAttribute("forumnum", thisforum.getAttribute("id"));
         menuel.setAttribute("onclick", "SAmenuitemCommand2(event,this,'click');");
         menuel.setAttribute("oncommand", "SAmenuitemCommand2(event,this,'command');");
         if (thisforum.getAttribute("cat") && thisforum.getAttribute("cat").substring(0,3)=="sub") {
            menuel.setAttribute("class", "lastread_menu_"+ thisforum.getAttribute("cat"));
         }
/*
         if (thisforum.getAttribute("cat")=="sub") {
            menuel.setAttribute("class", "lastread_menu_sub");
         }
         else if (thisforum.getAttribute("cat")=="sub-sub") {
            menuel.setAttribute("class", "lastread_menu_sub_sub");
         }
*/
         //TODO: access keys
         target.appendChild(menuel);
         if (nested_menus) {
            var thisforumnum = thisforum.getAttribute("id");
            for (var j=0; j<pinnedForumNumbers.length; j++) {
               if (pinnedForumNumbers[j]==thisforumnum) {
                  pinnedForumElements[j] = thisforum;
               }
            }
         }
      }
   }
}

function SALR_DEBUG_ViewXMLData() {
   var threads = selectNodes(persistObject.xmlDoc, persistObject.xmlDoc, "/salastread/thread");
   var nName = persistObject.xmlDoc.documentElement.nodeName;
   var nmsg;
   if (nName=="salastread") {
      nmsg = "This is correct.";
   } else {
      nmsg = "THIS IS NOT CORRECT.";
   }
   var tclen = persistObject._cachedThreadEntryList.length;
   alert("There are "+ threads.length + " threads stored.\nThe root is named "+nName+". "+nmsg+"\nThere are "+tclen+" entries in the CTEL.");
}

function SALR_DEBUG_ResetXMLData() {
   if ( confirm("Are you sure you want to reset the salastread.xml data?\nThis will lose all viewed threads, posted threads, and starred threads.") ) {
      persistObject._cachedThreadEntryList = new Array();

      persistObject.InitializeEmptySALRXML();
      persistObject.SaveXML();
      alert("salastread.xml has been reset.");
   } else {
      alert("Operation cancelled.");
   }
}

function SALR_InsertDebugMenuEntries(targetpopup) {
    var AME = function(lab, fnc) {
       var xfoo = document.createElement("menuitem");
       xfoo.setAttribute("label", lab);
       xfoo.addEventListener("command", fnc, false);
       targetpopup.appendChild(xfoo);
    };

    AME("View salastread.xml Data", function() { SALR_DEBUG_ViewXMLData(); });
    AME("Reset salastread.xml Data", function() { SALR_DEBUG_ResetXMLData(); });
    //AME("TEST FTP UPLOAD GOOD", function() { SALR_DEBUG_TestFTPUpload("s"); });
    //AME("TEST FTP UPLOAD BAD", function() { SALR_DEBUG_TestFTPUpload("b"); });
    //AME("TEST FTP DOWNLOAD GOOD", function() { SALR_DEBUG_TestFTPDownload("s"); });
    //AME("TEST FTP DOWNLOAD BAD", function() { SALR_DEBUG_TestFTPDownload("b"); });
    AME("Syncxx", function() { persistObject.FirefoxShuttingDown(); });
    AME("Normal Sync Call", function() { SALR_SyncTick(false,false); });
    AME("Force Sync Call", function() { SALR_SyncTick(true,false); });
    AME("TRACE CONFIG", function() { SALR_SyncTick(true,true); });
}

var SALR_DEBUG_pendingUpload = null;
var SALR_DEBUG_pendingDownload = null;

function SALR_DEBUG_TestFTPDownload(xx) {
   var url = "ftp://admin:"+ "x" +"@evercrest.com/test.txt";
   var localfile = "c:\\documents and settings\\tim fries\\testin.txt"
   alert("before download");
   SALR_DEBUG_pendingDownload = new SALR_FTPTransferObject();
   SALR_DEBUG_pendingDownload.getFile(url, localfile, SALR_DEBUG_TestFTPDownloadDone);
}

function SALR_DEBUG_TestFTPDownloadDone(status) {
   alert("status = "+status);
   SALR_DEBUG_pendingDownload = null;
}

function SALR_DEBUG_TestFTPUpload(xx) {
   var url = "ftp://admin:"+ "x" +"@evercrest.com/test.txt";
   var localfile = "c:\\documents and settings\\tim fries\\test.txt"

   alert("before upload");
   SALR_DEBUG_pendingUpload = new SALR_FTPTransferObject();
   SALR_DEBUG_pendingUpload.sendFile(url, localfile, SALR_DEBUG_TestFTPUploadDone);
}
function SALR_DEBUG_TestFTPUploadDone(result) {
   if (result==0)
      alert("upload succeeded");
   else
      alert("upload failed");
   SALR_DEBUG_pendingUpload = null;
}

function buildSAForumMenu() {
   try {
   if ( persistObject.toggle_hideOtherSAMenus ) {
      var mmb = document.getElementById("main-menubar");
      for (var x=0; x<mmb.childNodes.length; x++) {
         var thischild = mmb.childNodes[x];
         if (thischild.nodeName=="menu") {
            if ( (thischild.getAttribute("label")=="SA" || thischild.label=="SA" || thischild.id=="menu-sa") &&
                 thischild.id!="menu_SAforums") {
               mmb.removeChild(thischild);
               x--;
            }
         }
      }
   }
   var menupopup = document.getElementById("menupopup_SAforums");
   if (menupopup==null) {
      var iBefore = document.getElementById("bookmarks-menu");
      if (iBefore) {
         iBefore = iBefore.nextSibling;
      }
      if (!iBefore) {
         iBefore = document.getElementById("main-menubar").lastChild;
      }
      var menuel = document.createElement("menu");
      menuel.id = "menu_SAforums";
      menuel.setAttribute("label", "SA");
      menuel.setAttribute("accesskey","S");
      menuel.style.display = "none";
      menupopup = document.createElement("menupopup");
      menupopup.id = "menupopup_SAforums";
      menupopup.className = "lastread_menu";
      menuel.appendChild(menupopup);
      document.getElementById("main-menubar").insertBefore(menuel, iBefore);
      menupopup.addEventListener("popupshowing", SALR_SAMenuShowing, false);
   }
   if ( persistObject.toggle_useSAForumMenuBackground ) {
      menupopup.className = "lastread_menu";
   } else {
      menupopup.className = "";
   }
   while (menupopup.firstChild) {
      menupopup.removeChild(menupopup.firstChild);
   }
   var forumsDoc = persistObject.forumListXml;
   var nested_menus = persistObject.toggle_nestSAForumMenu;
   var menuel = document.createElement("menuitem");
   var pinnedForumNumbers = new Array();
   var pinnedForumElements = new Array();
   if (nested_menus && persistObject.string_menuPinnedForums) {
      pinnedForumNumbers = persistObject.string_menuPinnedForums.split(",");
   }
   menuel.setAttribute("label","Something Awful");
   menuel.setAttribute("image", "chrome://salastread/content/sa.png");
   menuel.setAttribute("onclick", "SAmenuitemCommandURL2(event,'http://www.somethingawful.com','click');");
   menuel.setAttribute("oncommand", "SAmenuitemCommandURL2(event,'http://www.somethingawful.com','command');");
   menuel.setAttribute("class","menuitem-iconic lastread_menu_frontpage");
   menuel.setAttribute("accesskey","s");
   menupopup.appendChild(menuel);
   menupopup.appendChild(document.createElement("menuseparator"));

   var lmenuel = document.createElement("menuitem");
   lmenuel.setAttribute("label","Configure SALastRead...");
   //lmenuel.setAttribute("onclick", "runConfig('click');");
   lmenuel.setAttribute("oncommand", "SALR_runConfig('command');");
   menupopup.appendChild(lmenuel);

   if ( persistObject.IsDebugEnabled() ) {
      var dmenuel = document.createElement("menu");
      dmenuel.setAttribute("label","SALR Debug");
      var dmenupopup = document.createElement("menupopup");

      SALR_InsertDebugMenuEntries(dmenupopup);

      dmenuel.appendChild(dmenupopup);
      menupopup.appendChild(dmenuel);
   }

   menupopup.appendChild(document.createElement("menuseparator"));

   populateForumMenuFrom(nested_menus,menupopup,forumsDoc.documentElement,pinnedForumNumbers,pinnedForumElements);

   if (nested_menus && pinnedForumElements.length > 0) {
      menupopup.appendChild(document.createElement("menuseparator"));
      for (var j=0; j<pinnedForumElements.length || j<pinnedForumNumbers.length; j++) {
         if (pinnedForumElements[j]) {
            var thisforum = pinnedForumElements[j];
            var menuel = document.createElement("menuitem");
            var forumname = thisforum.getAttribute("name");
            while (forumname.substring(0,1)==" ") {
               forumname = forumname.substring(1);
            }
            menuel.setAttribute("label", forumname);
            menuel.setAttribute("forumnum", thisforum.getAttribute("id"));
            menuel.setAttribute("onclick", "SAmenuitemCommand2(event,this,'click');");
            menuel.setAttribute("oncommand", "SAmenuitemCommand2(event,this,'command');");
            menuel.setAttribute("class", "lastread_menu_sub");
            menupopup.appendChild(menuel);
         }
         else if (pinnedForumNumbers[j]=="sep") {
            menupopup.appendChild( document.createElement("menuseparator") );
         }
         else if (typeof(pinnedForumNumbers[j])=="string" && pinnedForumNumbers[j].substring(0,3)=="URL") {
            var umatch = pinnedForumNumbers[j].match(/^URL\[(.*?)\]\[(.*?)\]$/);
            if (umatch) {
               var menuel = document.createElement("menuitem");
               menuel.setAttribute("label", persistObject.UnescapeMenuURL(umatch[1]));
               menuel.setAttribute("targeturl", persistObject.UnescapeMenuURL(umatch[2]));
               menuel.setAttribute("onclick", "SAmenuitemCommandURL2(event,this,'click');");
               menuel.setAttribute("oncommand", "SAmenuitemCommandURL2(event,this,'command');");
               menuel.setAttribute("class", "lastread_menu_sub");
               menupopup.appendChild(menuel);
            }
         }
         else if (pinnedForumNumbers[j]=="starred") {
            var menuel = document.createElement("menu");
            menuel.setAttribute("label", "Starred Threads");
            menuel.setAttribute("image", "chrome://salastread/content/star.png");
            menuel.setAttribute("class", "menu-iconic lastread_menu_starred");

            var subpopup = document.createElement("menupopup");
            subpopup.id = "salr_starredthreadmenupopup";

            menuel.appendChild(subpopup);
            menupopup.appendChild(menuel);

            subpopup.setAttribute("onpopupshowing", "SALR_StarredThreadMenuShowing();");
         }
      }
      if ( persistObject.toggle_showMenuPinHelper ) {
         var ms = document.createElement("menuseparator");
         ms.id = "salr_pinhelper_sep";
         menupopup.appendChild(ms);
         var menuel = document.createElement("menuitem");
         menuel.id = "salr_pinhelper_item";
         menuel.setAttribute("label", "Learn how to pin forums to this menu...");
         menuel.setAttribute("image", "chrome://salastread/content/eng101-16x16.png");
         menuel.setAttribute("oncommand", "SALR_LaunchPinHelper();");
         menuel.setAttribute("class", "menuitem-iconic lastread_menu_sub");
         menupopup.appendChild(menuel);
      }
   }

   document.getElementById("menu_SAforums").style.display = "-moz-box";
   } catch(exc) { alert("menuerr: "+exc); }
}

function SALR_StarredThreadMenuShowing() {
   //alert("here");
   var menupopup = document.getElementById("salr_starredthreadmenupopup");
   while (menupopup.firstChild != null) {
      menupopup.removeChild(menupopup.firstChild);
   }

   var starredThreads = selectNodes(persistObject.xmlDoc, persistObject.xmlDoc, "/salastread/thread[@star='1']");
   for (var i=0; i<starredThreads.length; i++) {
      var threadid = starredThreads[i].getAttribute("id");
      var threadtitle = typeof(starredThreads[i].getAttribute("title"))=='string' ? starredThreads[i].getAttribute("title") : "Unknown Thread Title ("+threadid+")";
      var menuel = document.createElement("menuitem");
      menuel.setAttribute("label", threadtitle);
      menuel.setAttribute("onclick", "SAmenuitemCommandGoToLastPost(event,this,'click',"+threadid+");");
      menuel.setAttribute("oncommand", "SAmenuitemCommandGoToLastPost(event,this,'command',"+threadid+");");
      menupopup.appendChild(menuel);
   }
}

function SALR_SAMenuShowing() {
   //alert("here - " + persistObject.toggle_showMenuPinHelper);
   if ( persistObject.toggle_showMenuPinHelper == false ) {
      var ms = document.getElementById("salr_pinhelper_sep");
      var mi = document.getElementById("salr_pinhelper_item");
      if ( ms != null ) {
         ms.parentNode.removeChild(ms);
      }
      if ( mi != null ) {
         mi.parentNode.removeChild(mi);
      }
   }
}

function SALR_LaunchPinHelper() {
   persistObject.toggle_showMenuPinHelper = false;
   persistObject.SavePrefs();
   SALR_runConfig("catMenuButton");
   alert("You may return to the menu settings at any time by choosing \"Configure SALastRead...\" from the SA menu, or by "+
         "clicking the \"Configure Last Read Extension\" link in the header of any forum page.");
}

/*
function grabForumList(e, selectnode) {
   var doc = e.originalTarget;
   var optionlist = selectNodes(doc, selectnode, "OPTION");
   var oDomParser = new DOMParser();
   var forumsDoc = oDomParser.parseFromString("<?xml version=\"1.0\"?>\n<forumlist></forumlist>", "text/xml");
   for (var i=0; i<optionlist.length; i++) {
      var thisopt = optionlist[i];
      var thisopttext = thisopt.firstChild.nodeValue;
      if ( thisopttext.substring(0,2)=="--" && thisopt.getAttribute("value")!="-1" ) {
         var fel = forumsDoc.createElement("forum");
         fel.setAttribute("id", thisopt.getAttribute("value"));
         fel.setAttribute("name", thisopttext.substring(2));
         forumsDoc.documentElement.appendChild(fel);
      }
   }
   persistObject.forumListXml = forumsDoc;
   if ( persistObject.toggle_showSAForumMenu ) {
      buildSAForumMenu();
   }
}

function buildSAForumMenu() {
   var menupopup = document.getElementById("menupopup_SAforums");
   while (menupopup.firstChild) {
      menupopup.removeChild(menupopup.firstChild);
   }
   var forumsDoc = persistObject.forumListXml;
   var forums = selectNodes(forumsDoc, forumsDoc.documentElement, "//forum");
   for (var i=0; i<forums.length; i++) {
      var thisforum = forums[i];
      var menuel = document.createElement("menuitem");
      menuel.setAttribute("label", thisforum.getAttribute("name"));
      menuel.setAttribute("forumnum", thisforum.getAttribute("id"));
      menuel.setAttribute("oncommand", "SAmenuitemCommand(this);"); // ", function(evt) { SAmenuitemCommand(evt); }, true );
      menupopup.appendChild(menuel);
   }
   document.getElementById("menu_SAforums").style.display = "-moz-box";
}
*/

function handleSubscribedThreadTable(e, subTable) {
   var doc = e.originalTarget;
   //alert("here " + subTable.nodeName);
   var threadRows = selectNodes(doc, subTable, "TBODY/TR");  //[@id!='cat']");
   var firstMatch = 1;
   for (var i=0; i<threadRows.length; i++) {
      var thisRow = threadRows[i];
      if ( thisRow.id != "cat" ) {
         if (firstMatch) {
            firstMatch = 0;
         } else {
            //var threadlink = selectNodes(doc, thisRow, "TD/FONT/A[contains(@href,'showthread.php')]")[0];
            var threadlink = selectSingleNode(doc, thisRow, "TD/FONT/A[contains(@href,'showthread.php')]");
            //var lpdata = selectNodes(doc, thisRow, "TD/TABLE[@id='ltlink']/TBODY/TR/TD/FONT")[0];
            var lpdata = selectSingleNode(doc, thisRow, "TD/TABLE[@id='ltlink']/TBODY/TR/TD/FONT");
            if (threadlink && lpdata) {
               var lpdate = StripSpaces(lpdata.firstChild.nodeValue);
               var lptime = StripSpaces(lpdata.firstChild.nextSibling.firstChild.nodeValue);
               var threadid = threadlink.href.match(/threadid=(\d+)/)[1];
               var isFYAD = 0;
               var setClasses = 0;
               //var topictitletd = selectNodes(doc, thisRow, "TD[3]")[0];
               var topictitletd = selectSingleNode(doc, thisRow, "TD[3]");
               //var topicretd = selectNodes(doc, thisRow, "TD[5]")[0];
               var topicretd = selectSingleNode(doc, thisRow, "TD[5]");

               setUpThreadIcons(doc,thisRow,threadid,lpdate,lptime,isFYAD,setClasses,topictitletd,topicretd,0);

               var ulinknode = selectSingleNode(doc, thisRow, "TD[4]//A[contains(@href,'action=getinfo')]");
               if (ulinknode) {
                  var uname = ulinknode.firstChild.nodeValue;
                  uname = uname.replace(/[^A-Z0-9]/gi, "_");
                  ulinknode.className += " somethingawfulforum_userlink_"+uname;
               }

               var llinknode = selectSingleNode(doc, thisRow, "TD[8]//A[contains(@href,'action=getinfo')]");
               if (llinknode) {
                  var uname = llinknode.firstChild.firstChild.nodeValue;
                  uname = uname.replace(/[^A-Z0-9]/gi, "_");
                  llinknode.className += " somethingawfulforum_userlink_"+uname;
               }
            }
         }
      }
   }
}

function handleSubscriptions(e) {
   //alert("member2");
   var doc = e.originalTarget;
   //var subForm = selectNodes(doc, doc.body, "//FORM[@method='get'][contains(@action,'member2.php')]")[0];
   var subForm = selectSingleNode(doc, doc.body, "//FORM[@method='get'][contains(@action,'member2.php')]");
   if (subForm) {
      var subTable = subForm.parentNode;
      handleSubscribedThreadTable(e, subTable);
   }
}

function setUpThreadIcons(doc,thisel,threadid,lpdate,lptime,isFYAD,setClasses,topictitletd,topicretd,forumid) {
   var lpdtvalue = ConvertLPDateTimeToNum(StripSpaces(lpdate), StripSpaces(lptime));
   var isunread = IsLPDateTimeNew(true, lpdtvalue, threadid);
   var isignored = IsThreadIgnored(threadid);
   if (isignored) {
      thisel.style.display = "none";
   }
   thisel.lpdtvalue = lpdtvalue;
   thisel.className += " salastread_thread_" + threadid;
   if (isunread=="unread") {
      if ( setClasses ) {
         thisel.className += " salastread_unreadthread";
      }
      if ( isFYAD ) {
         setUnreadFYADColors(doc, thisel, "TD");
      } else {
         setUnreadColors(doc, thisel, "TD");
      }
   } else {
      var unvisitDecolors = null;
      var knownLastPostID = null;
      if (isunread=="readwithnew") {
         if ( setClasses ) {
            thisel.className += " salastread_readwithnewthread";
         }
         unvisitDecolors = setReadWithNewColors(doc, thisel, "TD");
         knownLastPostID = GetLastPostID(threadid);
      } else {
         if ( setClasses ) {
            thisel.className += " salastread_readthread";
         }
         unvisitDecolors = setReadColors(doc, thisel, "TD");
      }

      var threadIconOrder = persistObject.string_threadIconOrder;
      for (var j=0; j<THREAD_ICON_COUNT; j++) {
         if ( threadIconOrder.indexOf(String(j)) == -1 ) {
            threadIconOrder = String(threadIconOrder) + String(j);
         }
      }

      var thtml = topictitletd.innerHTML;
      var ntable = doc.createElement("table");
      var ntbody = doc.createElement("tbody");
      var ntr = doc.createElement("tr");
      var ntd0 = doc.createElement("td");
      var ntd1 = doc.createElement("td");
      var ntd2 = doc.createElement("td");
      ntr.appendChild(ntd0);
      ntr.appendChild(ntd1);
      ntr.appendChild(ntd2);
      ntbody.appendChild(ntr);
      ntable.appendChild(ntbody);
      ntable.style.width = "100%";
      ntable.style.borderCollapse = "collapse";
      ntable.style.border = "none";
      ntd0.style.border = "none";
      ntd1.style.border = "none";
      ntd2.style.border = "none";
      ntd0.style.background = "transparent";
      ntd1.style.background = "transparent";
      ntd2.style.background = "transparent";
      ntd0.style.padding = "0px";
      ntd1.style.padding = "0px";
      ntd2.style.padding = "0px";
      ntd0.style.width = "1px";
      ntd1.style.width = "99%";
      ntd2.style.width = "1px";
      ntd2.style.whiteSpace = "nowrap";
      ntd2.style.textAlign = "right";
      topictitletd.innerHTML = "";

      // actually pretty slow
      //while ( topictitletd.firstChild != null ) {
      //   var el = topictitletd.firstChild;
      //   topictitletd.removeChild(el);
      //   ntd1.appendChild(el);
      //}

      topictitletd.appendChild(ntable);
      ntd1.innerHTML = thtml;

      var iconTargetElement = ntd2;
      //var iconTargetElement = topictitletd;

      while ( threadIconOrder ) {
         var thisicon = threadIconOrder.substring(0,1);
         threadIconOrder = threadIconOrder.substring(1);
         if ( thisicon == 1 ) {
            if ( !knownLastPostID && persistObject.toggle_alwaysShowGoToLastIcon ) {
               knownLastPostID = GetLastPostID(threadid);
            }
            if (knownLastPostID) {
               if ( persistObject.toggle_showGoToLastIcon ) {
                  //iconTargetElement.insertBefore(createGoToLastReadPostButton(doc, knownLastPostID), topictitletd.firstChild);
                  iconTargetElement.appendChild(createGoToLastReadPostButton(doc, knownLastPostID));
               }
            }
         }
         else if ( thisicon == 2 ) {
            if ( persistObject.toggle_showUnvisitIcon ) {
               //iconTargetElement.insertBefore( createUnvisitButton(doc, threadid, thisel, unvisitDecolors), topictitletd.firstChild );
               iconTargetElement.appendChild( createUnvisitButton(doc, threadid, thisel, unvisitDecolors, forumid) );
            }
         }
      }

      if ( cachedThreadEntry.getAttribute("star")=="1" ) {
         var ix = doc.createElement("img");
         ix.src = "chrome://salastread/content/star.png";
         ix.style.paddingRight = "5px";
         ix.style.display = "block";
         ntd0.style.width = "1px";
         ntd0.appendChild(ix);
      } else {
         ntd0.style.display = "none";
      }

      var hasPostedInThread = GetPostedInThread(threadid);
      if (hasPostedInThread) {
         if ( setClasses ) {
            thisel.className += " salastread_postedinthread";
         }
         topicretd.style.backgroundColor = persistObject.color_postedInThreadRe;
         if ( !persistObject.toggle_disableGradients ) {
            var bgtohighlight = persistObject.color_postedInThreadReHighlight;
            topicretd.style.backgroundImage = "url(x-salr-gradientpng:"+
                 SALRHexToNumber( bgtohighlight.substring(1,3) ) + "," +
                 SALRHexToNumber( bgtohighlight.substring(3,5) ) + "," +
                 SALRHexToNumber( bgtohighlight.substring(5,7) ) + "," +
                  "33)";
            topicretd.style.backgroundRepeat = "repeat-x";
         }
         topicretd.style.fontWeight = "bold";
      }

      if ( cachedThreadEntry.getAttribute("lastreplyct") ) {
         var lastreplyct = 0 + cachedThreadEntry.getAttribute("lastreplyct");
         var curreplyct = 0 + topicretd.firstChild.firstChild.nodeValue;
         if (curreplyct > lastreplyct) {
            var newsp = doc.createElement("span");
            newsp.className = "salastread_newreplycount";
            newsp.appendChild(doc.createTextNode(" ("+ (curreplyct-lastreplyct)+")"));
            topicretd.appendChild(newsp);
         }
      }
   }
}

function handleForumDisplay(e) {
   //alert("forumdisplay");
   var doc = e.originalTarget;
   
   //Replace post button
   if (persistObject.toggle_useQuickQuote) {
    var postbutton = selectSingleNode(doc, doc, "//UL[@class='postbuttons']//LI//A/IMG[contains(@src,'forum-post')]");
    if (postbutton) {
      makeQuickPostButton(undefined, doc, postbutton);
    }
   }


   // Snag Forum Moderators
   if ( persistObject.forumListXml ) {
      var saveXml = false;
      var fxml = persistObject.forumListXml;
      var mNodeContainer = selectSingleNode(doc, doc.body, "TABLE/TBODY[1]/TR[1]/TD[1]/TABLE[1]/TBODY[1]/TR[2]/TD[1]/DIV[contains(text(),'(Mods:')]");
      if (mNodeContainer) {
         var fidmatch = doc.location.href.match(/forumid=(\d+)/i);
         if (fidmatch) {
            var forumid = fidmatch[1];
            var mods = new Array();
            var modnames = new Array();
            var mNodes = selectNodes(doc, mNodeContainer, ".//A");
            for (var i=0; i<mNodes.length; i++) {
               var xhrefuid = mNodes[i].href.match(/userid=(\d+)/i);
               if (xhrefuid) {
                  mods.push( xhrefuid[1] );
                  modnames.push( SALR_MakeClassSafe( mNodes[i].innerHTML ) );
               }
            }
            var flForumEl = selectSingleNode( fxml, fxml, "//forum[@id='"+forumid+"']" );
            if ( flForumEl ) {
               flForumEl.setAttribute("mods", mods.join(","));
               flForumEl.setAttribute("modnames", modnames.join(","));
               saveXml = true;
            }
         }
      }
      if (saveXml) {
         persistObject.forumListXml = fxml;  // forces a save
      }
   }

   // Highlight Threads
   var gotOne = false;
   var resarray = selectNodes(doc, doc, "//TR[@class='thread']");
   //var resarray = selectNodes(doc, doc, "//A[@class='thread']");
   for (var x=0; x<resarray.length; x++) {
      var thisel = resarray[x];
      //while ( thisel.nodeName != "TR" ) {
      //   thisel = thisel.parentNode;
      //}
      if ( thisel.nodeName == "TR" ) {
         //var threadratingicon = selectSingleNode(doc, thisel, "TD[6]/IMG[contains(@src,'stars.gif')]");
         //if (threadratingicon) {
         //   threadratingicon.title = threadratingicon.alt;
         //}
         var isunread = false;
         var titleNode = selectSingleNode(doc, thisel, "TD[@class='title']");
         var threadLink = selectSingleNode(doc, titleNode, "A[1]");
         if (threadLink==null)
            continue;
       
         var timatch = threadLink.href.match(/threadid=(\d+)/);
         var threadid = timatch[1];
         gotOne = true;

/*
         var oldnode = 0;
         var lpdtnode = selectSingleNode(doc, thisel, "TD/TABLE[@id='ltlink']/TBODY/TR/TD/DIV[@class='mainbodytextsmall']");
         if (!lpdtnode) {
            // We're in Film Dump or something equally unrecognizable ... abort the mission
            // Well, maybe it's FYAD on the old HTML template, let's see..
            lpdtnode = selectSingleNode(doc, thisel, "TD/TABLE[@id='ltlink']/TBODY/TR/TD/FONT/FONT");
            oldnode = 1;
            if (!lpdtnode) {
               // Nope. Now we can abort.
               return;
            }
         }

         var lptime = "";
         var lpdate = "";
         if (oldnode==1) {
            lptime = StripSpaces(lpdtnode.firstChild.nodeValue);
            lpdate = StripSpaces(lpdtnode.nextSibling.nodeValue);
         } else {
            var lpdttext = lpdtnode.firstChild.nodeValue;
            lptime = StripSpaces( lpdttext.substring(0,5) );
            lpdate = StripSpaces( lpdttext.substring(6) );
         }
*/
         var lpdtnode = selectSingleNode(doc, thisel, "TD[@class='lastpost']/DIV[@class='date']");
         var lpdttext = lpdtnode.innerHTML;
         //alert("lpdttext="+lpdttext);
         lpdttext = StripSpaces(lpdttext);
         var lpdtm = lpdttext.match(/^(\d\d\:\d\d) (...) (\d\d), (\d\d\d\d)$/);
         if (!lpdtm) {
            return;
         }
         var lptime = lpdtm[1];
         var lpdate = lpdtm[2] + " " + lpdtm[3] + ", " + lpdtm[4];

         var forumid = 0;
         var fidmatch = doc.location.href.match(/forumid=(\d+)/i);
         if (fidmatch) {
            forumid = fidmatch[1];
         }
         var isFYAD = (forumid == 26);
         var isAskTell = (forumid == 158);
         if (isFYAD) {
            SALR_SilenceLoadErrors = true;
         }
         var setClasses = 1;
/*
         var rowTds = selectNodes(doc, thisel, "TD");
         var topictitletd = rowTds[1];
         var topicretd = rowTds[3];
         var topicAuthorTDIndex = 3;
         if ( isAskTell ) {
            topictitletd = rowTds[2];
            topicretd = rowTds[4];
            topicAuthorTDIndex = 4;
         }
*/
         var topictitletd = selectSingleNode(doc, thisel, "TD[@class='title']");
         var topicretd = selectSingleNode(doc, thisel, "TD[@class='replies']");

         setUpThreadIcons(doc,thisel,threadid,lpdate,lptime,isFYAD,setClasses,topictitletd,topicretd,forumid);

         //var ulinknode = selectSingleNode(doc, thisel, "TD["+topicAuthorTDIndex+"]/DIV/A[contains(@href,'action=getinfo')]");
         var ulinknode = selectSingleNode(doc, thisel, "TD[@class='author']/A[contains(@href,'action=getinfo')]");
         if (ulinknode) {
            var userid = 0;
            var uidmatch = ulinknode.href.match(/userid=(\d+)/i);
            if ( uidmatch ) {
               userid = uidmatch[1];
            }
            var uname = ulinknode.firstChild.nodeValue;
            uname = uname.replace(/[^A-Z0-9]/gi, "_");
            ulinknode.className += " somethingawfulforum_userlink_"+uname;
            if ( SALR_IsModerator(userid, forumid) ) {
               ulinknode.className += " somethingawfulforum_userlinkMODERATOR";
            }

            persistObject.StoreOPData(threadid, userid);
/*
            var renewOPFunc = SALR_CreateOPFunc(threadid, uid);

            var linkslist = selectNodes(doc, thisel, ".//A");
            for (var i=0; i<linkslist.length; i++) {
               linkslist[i].addEventListener("focus", renewOPFunc, false);
               linkslist[i].addEventListener("click", renewOPFunc, false);
               linkslist[i].addEventListener("contextmenu", renewOPFunc, false);
               //linkslist[i].style.background = "red";
            }
*/
         }

         var ulinknodeb = selectSingleNode(doc, thisel, "TD[@class='lastpost']/A[@class='author'][contains(@href,'goto=lastpost')]");
         if (ulinknodeb) {
            var uname = ulinknodeb.firstChild.nodeValue;
            uname = uname.replace(/[^A-Z0-9]/gi, "_");
            ulinknodeb.className += " somethingawfulforum_userlink_"+uname;
            if ( SALR_IsModerator(uname, forumid) ) {
               ulinknodeb.className += " somethingawfulforum_userlinkMODERATOR";
            }
         }

      }
   }
   if (gotOne) {
      var csstxt = SALR_MakeForumDisplayCSS();
      //alert("csstxt =\n"+csstxt);
      var cssObj = doc.createElement("style");
      cssObj.type = "text/css";
      cssObj.innerHTML = csstxt;
      doc.getElementsByTagName('head')[0].appendChild(cssObj);
   }

   return resarray.length;
}

/*
function SALR_CreateOPFunc(threadid, uid) {
   return function() {
      persistObject._cachedOP = { t: threadid, op: uid };
   };
}
*/

function SALR_MakeClassSafe(unsafestr) {
   var result = unsafestr.replace(/[^A-Za-z0-9]/,"_");
   return result;
}

function createGoToLastReadPostButton(doc, lkpid) {
   var golink = doc.createElement("A");
   golink.href = "http://forums.somethingawful.com/showthread.php?s=&postid="+lkpid+"#post"+lkpid;
   golink.className = "salastreadicon";
   var goimg = doc.createElement("IMG");
   goimg.src = persistObject.url_goToLastReadPost;
   //goimg.style.cssFloat = "right";
   goimg.style.border = "none";
   goimg.style.marginLeft = "3px";
   golink.appendChild(goimg);
   return golink;
}

function createUnvisitButton(doc, threadid, topicrow, unvisitDecolors, forumid) {
   var dellink = doc.createElement("A");
   dellink.href = "javascript:void(0);";
   dellink.className = "salastreadicon";
   dellink.id = "salastread_dellink" + threadid;
   dellink.addEventListener("click", function(ce) { unvisitThread(doc, persistObject, threadid, topicrow, unvisitDecolors, forumid); }, true);
   var delimg = doc.createElement("IMG");
   delimg.src = persistObject.url_markThreadUnvisited;
   //delimg.style.cssFloat = "right";
   delimg.style.border = "none";
   delimg.style.marginLeft = "3px";
   dellink.appendChild(delimg);
   return dellink;
}

function unvisitThread(doc, pobj, threadid, topicrow, unvisitDecolors, forumid) {
   //alert("unvisiting "+threadid);
   try {
   var xmlDoc = pobj.xmlDoc;
   var threads = selectNodes(xmlDoc, xmlDoc, "/salastread/thread[@id='"+threadid+"']");
   for (var i=0; i<threads.length; i++) {
      threads[i].parentNode.removeChild(threads[i]);
   }
   if ( forumid == 0 ) {
      resetUnreadColors(unvisitDecolors);
   } else {
      if ( !persistObject.toggle_dontHighlightThreads ) { 
         var threadrows = selectNodes(doc, topicrow, ".");
         for (var x=0; x<threadrows.length; x++) {
            threadrows[x].className = "thread salastread_thread_" + threadid + " salastread_unreadthread";
         }
     }
   }

   var icons = selectNodes(doc, topicrow, ".//A[@class='salastreadicon']");
   for (var j=0; j<icons.length; j++) {
      icons[j].parentNode.removeChild(icons[j]);
   }
   invalidateThreadCache();
   //pobj.SaveXML();
   persistObject.RemovePostDataSQL(threadid);
   } catch(e) { alert ("SALastRead unvisit fail: "+e); };
}

function replaceEmoticons(rawhtml) {
   rawhtml = rawhtml.replace(/<img src="http:\/\/forumimages\.somethingawful\.com\/images\/smilies\/emot-crying.gif" alt="" border="0">/g,":cry:");
   rawhtml = rawhtml.replace(/<img src="http:\/\/forumimages\.somethingawful\.com\/images\/smilies\/emot-(.*?)\.gif" alt="" border="0">/g,":$1:");
   rawhtml = rawhtml.replace(/<img src="http:\/\/i\.somethingawful\.com\/forumsystem\/emoticons\/emot-(.*?)\.gif" alt="" border="0">/g,":$1:");
   rawhtml = rawhtml.replace(/<img src="http:\/\/forumimages\.somethingawful\.com\/images\/smilies\/frown.gif" alt="" border="0">/g,":(");
   rawhtml = rawhtml.replace(/<img src="http:\/\/forumimages\.somethingawful\.com\/images\/smilies\/smile.gif" alt="" border="0">/g,":)");
   rawhtml = rawhtml.replace(/<img src="http:\/\/forumimages\.somethingawful\.com\/images\/smilies\/confused.gif" alt="" border="0">/g,":confused:");
   rawhtml = rawhtml.replace(/<img src="http:\/\/forumimages\.somethingawful\.com\/images\/smilies\/cool.gif" alt="" border="0">/g,":cool:");
   rawhtml = rawhtml.replace(/<img src="http:\/\/forumimages\.somethingawful\.com\/images\/smilies\/biggrin.gif" alt="" border="0">/g,":D");
   rawhtml = rawhtml.replace(/<img src="http:\/\/forumimages\.somethingawful\.com\/images\/smilies\/mad.gif" alt="" border="0">/g,":mad:");
   rawhtml = rawhtml.replace(/<img src="http:\/\/forumimages\.somethingawful\.com\/images\/smilies\/redface.gif" alt="" border="0">/g,":o");
   rawhtml = rawhtml.replace(/<img src="http:\/\/forumimages\.somethingawful\.com\/images\/smilies\/rolleyes.gif" alt="" border="0">/g,":rolleyes:");
   rawhtml = rawhtml.replace(/<img src="http:\/\/forumimages\.somethingawful\.com\/images\/smilies\/wink.gif" alt="" border="0">/g,";)");
   rawhtml = rawhtml.replace(/<img src="http:\/\/forumimages\.somethingawful\.com\/images\/smilies\/wink.gif" alt="" border="0">/g,";)");
   rawhtml = rawhtml.replace(/<img src="http:\/\/i\.somethingawful\.com\/mjolnir\/images\/livestock~01-14-04-whore.gif" alt="" border="0">/g,";-*");
   return rawhtml;
}

function getQuoteCodeFromButton(doc,quotebutton,postername) {
/*
   var thisel = quotebutton;
   while (thisel && !thisel.className.match(/post\d+/)) {
      thisel = thisel.parentNode;
   }
   if (!thisel)
      return "";
   var tid = thisel.SALR_threadid;
   if (!tid) return "";

   window.__salastread_quotepostid = tid;
*/
   return"";
}

function convertPLTag(message) {
   return message.replace(/\[PL=(.*?)\](.*?)\[\/PL\]/g,"[URL=http://forums.somethingawful.com/showthread.php?s=&postid=$1#post$1]$2[/URL]");
   //return message.replace(/\[PL=(.*?)\](.*?)\[\/PL\]/g,"[URL=http://forums.somethingawful.com/showthread.php?s=&action=showpost&postid=$1]$2[/URL]");
}

function parsePLTagsInEdit(tarea) {
   var xtxt = tarea.value;
   tarea.value = convertPLTag(xtxt);
}

var quickquotewin = null;

function releaseQuickQuoteVarsWithClose() {
   quickquotewin.close();
}

function releaseQuickQuoteVars() {
   window.__salastread_quotedoc = null;
   window.__salastread_quotetext = null;
   window.__salastread_quotethreadid = null;
   window.__salastread_quotepostid = null;
   window.__salastread_alreadypostedinthread = null;
   window.__salastread_needretrieval = null;
   quickQuoteSubmitting = false;
   quickquotewin = null;
}

function quickQuoteAddHidden(doc,form,name,value) {
   var newel = doc.createElement("INPUT");
   newel.type = "hidden";
   newel.name = name;
   newel.value = value;
   form.appendChild(newel);
}

function quickQuoteAddFile(doc,form,name,value) {
   var newel = doc.createElement("INPUT");
   newel.type = "file";
   newel.name = name;
   newel.value = value;
   form.appendChild(newel);
}

var quickQuoteSubmitting = false;
var salastread_savedQuickReply = "";
var salastread_savedQuickReplyThreadId = "";

function quickQuoteSubmit(message, parseurl, subscribe, disablesmilies, signature, subtype, formkey, attachfile) {
   try {
   message = convertPLTag(message);
   salastread_savedQuickReply = message;
   salastread_savedQuickReplyThreadId = window.__salastread_quotethreadid;
   //alert("here");
   var doc = window.__salastread_quotedoc;
   var newform = doc.createElement("FORM");
   newform.style.display = "none";
   newform.action = "http://forums.somethingawful.com/newreply.php";
   if (!window.__salastread_quotethreadid)
      newform.action = "http://forums.somethingawful.com/newthread.php";
   if (quickquotewin.__salastread_is_edit)
      newform.action = "http://forums.somethingawful.com/editpost.php";
   newform.method = "post";
   newform.enctype = "multipart/form-data";
   quickQuoteAddHidden(doc,newform,"s","");
   if (window.__salastread_quotethreadid) {
    if (quickquotewin.__salastread_is_edit) {
      quickQuoteAddHidden(doc,newform,"action","updatepost");
      quickQuoteAddHidden(doc, newform, "postid", window.__salastread_quotepostid);
    }
    else {
      quickQuoteAddHidden(doc,newform,"action","postreply");
      quickQuoteAddHidden(doc,newform,"threadid", window.__salastread_quotethreadid);
    }
   }
   else {
    quickQuoteAddHidden(doc,newform,"action","postthread");
    quickQuoteAddHidden(doc, newform, "forumid",  quickquotewin.__salastread_quickpost_forumid);
    quickQuoteAddHidden(doc, newform, "iconid", quickquotewin.document.getElementById('posticonbutton').iconid);
    quickQuoteAddHidden(doc, newform, "subject", quickquotewin.document.getElementById('subject').value);   
   }
   quickQuoteAddHidden(doc,newform,"parseurl", parseurl ? "yes" : "");
   quickQuoteAddHidden(doc,newform,"email", subscribe ? "yes" : "");
   quickQuoteAddHidden(doc,newform,"disablesmilies", disablesmilies ? "yes" : "");
   quickQuoteAddHidden(doc,newform,"signature", signature ? "yes" : "");
   quickQuoteAddHidden(doc,newform,"message", message);
   quickQuoteAddHidden(doc,newform,"MAX_FILE_SIZE", "2097152");
   quickQuoteAddHidden(doc,newform,"formkey", formkey);
   if (attachfile!="") {
      quickQuoteAddFile(doc,newform,"attachment", attachfile);
   }
   newform.__submit = newform.submit;
   if (window.__salastread_quotethreadid) {
     if (subtype=="submit") {
        quickQuoteAddHidden(doc,newform,"submit","Submit Reply");
        markThreadReplied(persistObject, window.__salastread_quotethreadid);
     } else {
        quickQuoteAddHidden(doc,newform,"preview","Preview Reply");
     }
   }
   else {
     quickQuoteAddHidden(doc,newform,"preview","Preview Post");
   }
   doc.body.appendChild(newform);
   //alert(newform.innerHTML);
   quickQuoteSubmitting = true;
   newform.__submit();
   quickquotewin.close();
   } catch(e) { alert("err: "+e); }
}

function salastread_windowOnBeforeUnload(e) {
   if ( persistObject._killed==true ) { return; }
   if ( e.originalTarget == window.__salastread_quotedoc ) {
      if (quickQuoteSubmitting) {
         return true;
      }
/*
      alert("If you navigate away from this page, the Quick Reply window will close, since it will "+
            "no longer have a page to target to submit the reply to (this will probably be fixed "+
            "in a future release).  If you want to cancel this navigation, choose 'Cancel' in the "+
            "next dialog box that will appear.");
      e.stopPropagation();
      e.preventDefault();
      return false;
*/
      if (quickquotewin && !quickquotewin.closed) {
         quickquotewin.detachFromDocument();
      }
      return true;
   }
}

var SALR_PageTimerCount = 0;

function SALR_IncTimer() {
   SALR_PageTimerCount++;
}

function SALR_DecTimer() {
   SALR_PageTimerCount--;
}

function SALR_TimerTick() {
   if ( SALR_PageTimerCount > 0 && persistObject ) {
      persistObject.PingTimer();
   }
}

function SALR_SyncTick(force,trace) {
   var xforce = force ? true : false;
   trace = (trace==true) ? true : false;
   if (persistObject) {
      var res;
      if (trace)
         res = persistObject.PerformRemoteSync(xforce, function(){}, function(a){alert(a);});
      else
         res = persistObject.PerformRemoteSync(xforce, function(){}, function(a){});
      if (xforce) { alert("res.bad = "+res.bad+"\nres.msg = "+res.msg); }
   }
}

function salastread_windowOnUnload(e) {
   if ( persistObject._killed==true ) { return; }
   if ( e.originalTarget == window.__salastread_quotedoc ) {
      //releaseQuickQuoteVarsWithClose();
      releaseQuickQuoteVars();
   }
   if ( e.originalTarget.__salastread_processed ) {
      SALR_DecTimer();
      persistObject.SaveTimerValue();
   }
//   var pageTimer = e.originalTarget.__SALASTREAD_PAGETIMER;
//   if (pageTimer) {
//      pageTimer.Finalize();
//      e.originalTarget.__SALASTREAD_PAGETIMER = null;
//      var newPageTimers = new Array();
//      for (var i=0; i<thisWindowPageTimers.length; i++) {
//        if ( thisWindowPageTimers[i] != pageTimer ) {
//           newPageTimers.push( thisWindowPageTimers[i] );
//        }
//      }
//      thisWindowPageTimers = newPageTimers;
//   }
}

function cleanupLostPageTimers() {
   // because attaching to the unload event dynamically doesn't appear to work ...
   var cont = document.getElementById("content");
   var browsers = cont.browsers;
   var newPageTimers = new Array();
   for (var i=0; i<thisWindowPageTimers.length; i++) {
      var thisTimer = thisWindowPageTimers[i];
      var gotThisOne = 0;
      for (var j=0; j<browsers.length; j++) {
         var thisBrowser = browsers[j];
         if (thisBrowser.contentDocument && thisBrowser.contentDocument.__SALASTREAD_PAGETIMER==thisTimer) {
            gotThisOne = 1;
            newPageTimers.push(thisTimer);
         }
      }
      if (gotThisOne==0) {
         thisTimer.Finalize();
      }
   }
   thisWindowPageTimers = newPageTimers;
}

//function quickQuoteButtonClick(evt,threadid,/*doc,quotebutton,*/postername,isDoubleClick,hasQuote) {
function quickQuoteButtonClick(evt/*,threadid,postername,isDoubleClick,hasQuote*/) {
   var doc = evt.originalTarget.ownerDocument;
   var quotebutton = evt.originalTarget;
   var threadid = quotebutton.__salastread_threadid;
   var forumid = quotebutton.SALR_forumid;
   var postername = quotebutton.__salastread_postername;
   var hasQuote = quotebutton.__salastread_hasQuote;
   var is_edit = quotebutton.is_edit;
   var isDoubleClick = 0;

   if ( persistObject.__QuickQuoteWindowObject && !persistObject.__QuickQuoteWindowObject.closed ) {
      quickquotewin = persistObject.__QuickQuoteWindowObject;
   }

   window.__salastread_needretrieval = false;
   window.__salastread_quotedoc = doc;
   if (hasQuote) {
      // don't deparse anymore since we need the formkey anyway
      // on second thought, still need to call so quotepostid is set
      window.__salastread_quotetext = getQuoteCodeFromButton(doc, quotebutton, postername);
      window.__salastread_quotepostid = quotebutton.__salastread_postid;
      //window.__salastread_quotetext = "";
      if ( window.__salastread_quotetext == "" ) {
         window.__salastread_needretrieval = true;
      }
   } else {
      window.__salastread_quotetext = "";
      window.__salastread_quotepostid = null;
   }
   if (forumid) window.__salastread_needretrieval = true;
   window.__salastread_quotethreadid = threadid;
   window.__salastread_alreadypostedinthread = GetPostedInThread(threadid);
   if (!isDoubleClick && quickquotewin && !quickquotewin.closed) {
      try {
         //quickquotewin.addQuoteText(window.__salastread_quotetext);
         if (hasQuote) {
            quickquotewin.addQuoteFromPost(window.__salastread_quotepostid);
         }
         quickquotewin.focus();
      } catch(ex) {
         quickquotewin = window.open("chrome://salastread/content/quickquote.xul",
               "quickquote",
               "chrome, resizable=yes, width=800, height=400");
      }
   } else {
      quickquotewin = window.open("chrome://salastread/content/quickquote.xul",
               "quickquote",
               "chrome, resizable=yes, width=800, height=400");
   }
   if (quickquotewin) {
      persistObject.__QuickQuoteWindowObject = quickquotewin;
      quickquotewin.__salastread_quickpost_forumid = forumid;
      quickquotewin.__salastread_is_edit = is_edit;
   }
   return false;
}

function __unused() {
   try {
      var newdiv = doc.createElement("DIV");
      //newdiv.message = "woo woo woo";
      newdiv.style.position = "fixed";
      newdiv.style.top = "2%";
      newdiv.style.left = "2%";
      newdiv.style.width = "96%";
      newdiv.style.height = "50%";
      newdiv.style.zIndex = "13294945";
      newdiv.style.border = "1px solid #c1c1c1";
      newdiv.style.MozBinding = "url('chrome://salastread/content/quickquote.xml#quickquote')";
      doc.body.appendChild(newdiv);
      //newdiv.setAttribute("message", getQuoteCodeFromButton(doc,quotebutton) );
      newdiv.message = getQuoteCodeFromButton(doc,quotebutton,postername);
   }
   catch (e) {
      alert("err: "+e);
   }
   return false;
}

function attachQuickQuoteHandler(threadid,doc,quotebutton,postername,hasQuote,postid) {
   quotebutton.__salastread_threadid = threadid;
   quotebutton.__salastread_postid = postid;
   quotebutton.__salastread_postername = postername;
   quotebutton.__salastread_hasQuote = hasQuote;
   quotebutton.addEventListener("click", quickQuoteButtonClick, true);
   //quotebutton.onclick = function(evt) { return quickQuoteButtonClick(evt,threadid,/*doc,quotebutton,*/postername,0,hasQuote); };
   //quotebutton.ondblclick = function(evt) { return quickQuoteButtonClick(evt,threadid,/*doc,quotebutton,*/postername,1,hasQuote); };
}

var SALR_debugLog = new Array();
function addInternalDebugLog(msg) {
   SALR_debugLog.push( (new Date()).toString() +": "+msg );
   if ( SALR_debugLog.length > 10 ) {
      SALR_debugLog.shift();
   }
}

function SALR_ProcessPostImages(thisel) {
   var doc = thisel.ownerDocument;
   if ( persistObject.toggle_convertTextToImage ) {
      var mayBeNws = false;
      if ( persistObject.toggle_dontTextToImageIfMayBeNws ) {
         var ptext = thisel.innerHTML;
         if ( ptext.match(/nsfw/i) || ptext.match(/nws/i) ||
              ptext.match(/work safe/i) || ptext.match(/safe for work/i) ||
              ptext.match(/nms/i) ) {
            mayBeNws = true;
         }
      }
      if (!mayBeNws)
         SALR_TextToImage(thisel);
   }


   if (persistObject.toggle_thumbnailAllImages) {
      setTimeout(function() {

         var bodyimagenodes = selectNodes(doc, thisel, "TBODY/TR[1]/TD[2]/descendant::IMG");
         for (var lnum=0; lnum<bodyimagenodes.length; lnum++) {
            var thisimage = bodyimagenodes[lnum];
            thisimage.className += " SALR_need_thumbnailing";
            thisimage.addEventListener("load", SALR_PostImageResize, false);
            thisimage.addEventListener("resize", SALR_PostImageResize, false);
            thisimage.addEventListener("click", SALR_PostImageClick, false);
            thisimage.addEventListener("mouseout", SALR_PostImageMouseOut, false);
            thisimage.addEventListener("mouseover", SALR_PostImageMouseOver, false);
            var xx = { target: thisimage };
            SALR_PostImageResize(xx);
         }
      },1);
   }
}

// Ensure these correspond to the settings in thumbnail-images.css
var SALR_THUMBNAIL_MAX_WIDTH = 250;
var SALR_THUMBNAIL_MAX_HEIGHT = 250;

function SALR_PostImageClick(e) {
   var image = e.target;
   if (image.className.indexOf("SALR_thumbnail_fullsize")!=-1) {
      var cx = image.className.split(" ");
      var ncx = new Array();
      for (var i=0; i<cx.length; i++) {
         if (cx[i]!="SALR_thumbnail_fullsize")
            ncx.push(cx[i]);
      }
      image.className = ncx.join(" ");
   } else {
      image.className += " SALR_thumbnail_fullsize";
   }
   SALR_PostImageResize(e);
}

function SALR_PostImageMouseOver(e) {
   SALR_PostImageResizerShowHide(true, e);
}

function SALR_PostImageMouseOut(e) {
   SALR_PostImageResizerShowHide(false, e);
}

function SALR_PostImageResizerShowHide(show, e) {
   var image = e.target;
   var doc = image.ownerDocument;
   if (!image.__SALR_ThumbnailControl) {
	SALR_BuildThumbnailControl(doc,image);
    SALR_ToggleThumbnailControl(image,true)
   }
   if (image.SALR_imageResizable == undefined && image.className.indexOf("SALR_thumbnail_fullsize") == -1) {
	  if(image.offsetWidth == image.naturalWidth && image.offsetHeight == image.naturalHeight) {
		  image.SALR_imageResizable = false
	  } else {
		  image.SALR_imageResizable = true
	  }
   }

   if(image.SALR_imageResizable != undefined && !image.SALR_imageResizable) { 
	   return
   }

   if (image.__SALR_ThumbnailControl) {
      if (show) {
         image.__SALR_ThumbnailControl.style.display = "block";
         if (image.__SALR_ThumbnailHideTimer) {
            clearTimeout(image.__SALR_ThumbnailHideTimer);
            image.__SALR_ThumbnailHideTimer = null;
         }
      } else {
         image.__SALR_ThumbnailHideTimer = setTimeout(function() {
            image.__SALR_ThumbnailHideTimer = null;
            image.__SALR_ThumbnailControl.style.display = "none";
         }, 1000);
      }
   }
}


function SALR_PostImageResize(e) {
   var image = e.target;
   var doc = image.ownerDocument;

   if (!image.__SALR_ThumbnailControl) {
	 SALR_BuildThumbnailControl(doc,image);
   }

   if (image.className.indexOf("SALR_thumbnail_fullsize")!=-1) {
	 SALR_ToggleThumbnailControl(image,true)
   } else {
	 SALR_ToggleThumbnailControl(image,false)
   }
}

function SALR_ToggleThumbnailControl(image,up) {
	var tc = image.__SALR_ThumbnailControl;
	var tci = tc.firstChild;
	if(up) {
		tci.__up = true;
		tci.src = "chrome://salastread/content/scale_image_up.png";
	} else {
		tci.__up = false;
		tci.src = "chrome://salastread/content/scale_image.png";
	}
}

function SALR_BuildThumbnailControl(doc,image) {
	var outer = doc.createElement("div");
	outer.style.position = "absolute";
	outer.style.display = "none";
	var inner = doc.createElement("img");
	inner.src = "chrome://salastread/content/scale_image_up.png";
	inner.style.position = "relative";
	inner.style.top = "-11px";
	inner.style.left = "-11px";
	inner.style.width = "22px";
	inner.style.height = "22px";
	inner.style.border = "none";
	inner.style.cursor = "pointer";
	inner.onclick = function() { SALR_PostImageClick( {target: image} ); return false; };
	inner.onmouseover = function() { SALR_PostImageMouseOver( {target: image} ); return false; };
	inner.onmouseout = function() { SALR_PostImageMouseOut( {target: image} ); return false; };
	outer.appendChild(inner);
	image.parentNode.insertBefore(outer, image);
	image.__SALR_ThumbnailControl = outer;
}

function SALR_TextToImage(thisel) {
   var doc = thisel.ownerDocument;
   var bodylinknodes = selectNodes(doc, thisel, "TBODY/TR[1]/TD[2]/descendant::A");
   for (var lnum=0; lnum<bodylinknodes.length; lnum++) {
      var isimage = false;
      var thislink = bodylinknodes[lnum];
      var imgurl = thislink.href;
      if ( imgurl.match(/\.(gif|jpg|jpeg|png)$/i) ) {
         isimage = true;
      }
      var thmatch = imgurl.match(/^(.*)\.th(\..*)$/);
      if (thmatch) {
         imgurl = thmatch[1]+thmatch[2];
      }
      if ( imgurl.indexOf("?")!=-1 ) {
         isimage = false;
      }
      if ( selectSingleNode(doc, thislink, "IMG") ) {
         isimage = false;
      }
      if (isimage) {
         var abortTTI = false;
         if ( persistObject.toggle_dontTextToImageInSpoilers ) {
            var cel = thislink;
            while (cel!=null) {
               if (cel.className.indexOf("spoiler")!=-1) {
                  abortTTI = true;
                  break;
               }
               if (cel.className.indexOf("somethingawfulforum_postby")!=-1) {
                  break;
               }
               cel = cel.parentNode;
            }
         }
         if (!abortTTI) {
            var nimg = doc.createElement("img");
            if ( thislink.childNodes.length==1 &&
                 thislink.firstChild.nodeName=="#text" &&
                 thislink.firstChild.nodeValue.indexOf("http")==0 ) {
               // special case to replace a link containing only the url text completely
               thislink.removeChild(thislink.firstChild);
            }
            if ( thislink.nextSibling ) {
               thislink.parentNode.insertBefore(nimg, thislink.nextSibling);
            } else {
               thislink.parentNode.appendChild(nimg);
            }
            nimg.style.border = "2px dotted red";
            nimg.src = imgurl;
            nimg.title = "Text link converted to image automatically by SALR";
            if ( persistObject.toggle_shrinkTextToImages ) {
               setupThumbnailImage(nimg,false,true);
            }
         }
      }
   }
}

function handleShowThread(e) {
   var doc = e.originalTarget;

   if (doc.body.id != "something_awful" && doc.body.id != "all")
      return;
   var inFYAD = false;
   var inBYOB = false;

   var isloggedin = true;
   //if ( selectSingleNode(doc, doc.body, "TABLE/TBODY[1]/TR[1]/TD[1]/TABLE[1]/TBODY[1]/TR[1]/TD[1]/TABLE[1]/TBODY[1]/TR[1]/TD[1]//A[contains(@href,'action=loginform')]") ) {
   if ( doc.getElementById("notregistered") ) {
      isloggedin = false;
   }

   // Grab the go to dropdown
   if ( !persistObject.gotForumList ) {
      // Don't update from the dropdown in the gas chamber, because it contains Who's Online for some reason.
      var gasnode = selectSingleNode(doc, doc.body, "//TABLE[@align='center']/TBODY/TR[1]/TD[1]//B[1]/A[3][contains(@href,'forumdisplay.php')][contains(@href,'forumid=25')]");
      if (!gasnode) {
         var selectnode = selectSingleNode(doc, doc.body, "//SELECT[@name='forumid']");
         if (selectnode) {
            grabForumList(e, selectnode);
            persistObject.gotForumList = true;
         }
      }
   }

   var forumid = 0;
   //var forumidnodes = selectNodes(doc, doc.body, "TABLE/TBODY/TR[1]/TD[1]/TABLE[@align='center']/TBODY/TR[1]/TD[1]/SPAN[@class='mainbodytextlarge']/B[1]/A[contains(@href,'forumdisplay.php')][contains(@href,'forumid=')]");
   var forumidnodes = selectNodes(doc, doc.getElementById("container"), "DIV[@class='breadcrumbs']/SPAN/B/A[contains(@href,'forumdisplay.php')][contains(@href,'forumid=')]");
   if (forumidnodes && forumidnodes.length>0) {
      forumid = forumidnodes[forumidnodes.length-1].href.match(/forumid=(\d+)/i)[1];
   }
   doc.__SALR_forumid = forumid;
   doc.body.className += " salastread_forum"+forumid
   //alert("forumid = "+forumid);
   if (forumid == 174)
   	{
   	 inBYOB = true;
   	}
   // Figure out the current threadid
   var threadid;
   var timatch = doc.location.href.match( /threadid=(\d+)/ );
   if ( timatch ) {
      threadid = timatch[1];
   } else {
      //var sublinknode = selectSingleNode(doc, doc.body, "//A[contains(@href,'member2.php')][contains(@href,'threadid=')]");
      var sublinknode = selectSingleNode(doc, doc.getElementById("container"), "DIV[@class='subscribe']/A[contains(@href,'member2.php')][contains(@href,'threadid=')]");
      if (sublinknode) {
         var hrefmatch = sublinknode.href.match( /threadid=(\d+)/ );
         if (hrefmatch) {
            //alert("here here [1] - " + hrefmatch[1]);
            threadid = hrefmatch[1];
         }
      }
   }
   if ( !threadid ) {
      return;
   }
   doc.__SALR_threadid = threadid;

   // used by the context menu to allow options for this thread
   doc.body.className += " salastread_thread_"+threadid;

   // DEBUG:
   slurpIntoThreadCache(threadid);
   if (cachedThreadEntry) {

      var needSave = false;
/*
      if ( persistObject._cachedOP && persistObject._cachedOP.t == threadid ) {
         if ( cachedThreadEntry.getAttribute("op") != persistObject._cachedOP.op ) {
            cachedThreadEntry.setAttribute("op", persistObject._cachedOP.op);
            needSave = true;
         }
      }
*/
      var sop = persistObject.GetOPFromData(threadid);
      if ( sop && sop != cachedThreadEntry.getAttribute("op") ) {
         cachedThreadEntry.setAttribute("op", sop);
         needSave = true;
      }

      var threadtitle = "";
      var titlematch = doc.title.match( /^The Something Awful Forums \- (.*)$/ );
      if (titlematch) {
         threadtitle = titlematch[1];
      } else {
         var titlematchb = doc.title.match( /^(.*) \- The Something Awful Forums$/ );
         if (titlematchb) {
            threadtitle = titlematchb[1];
         }
      }
      if (threadtitle != "") {
         //alert("thread title = "+titlematch[1]);
         if ( !cachedThreadEntry.getAttribute("title") || cachedThreadEntry.getAttribute("title") != threadtitle ) {
            cachedThreadEntry.setAttribute("title", threadtitle);
            needSave = true;
            //persistObject.SaveXML();
         }
      } else {
         //alert("XX thread title = "+doc.title);
      }

      if (needSave) {
         //persistObject.SaveXML();
         var threaddetails = new Array();
         threaddetails['id'] = threadid;
         threaddetails['title'] = cachedThreadEntry.getAttribute("title");
         threaddetails['lastviewdt'] = cachedThreadEntry.getAttribute("lastviewdt");
         threaddetails['op'] = cachedThreadEntry.getAttribute("op");
         persistObject.SavePostDataSQL(threaddetails);
      }
   }
   var lpbefore = 0;
   if (cachedThreadEntry) {
      lpbefore = cachedThreadEntry.getAttribute("lastpostid");
   }
   var lpafter = 0;
   //addInternalDebugLog("showthread.php handler, thread #"+threadid+", lpbefore="+lpbefore+", lpafter="+lpafter);

   // See if this thread is closed
   var threadClosed = false;
   //if ( selectSingleNode(doc, doc.body, "//IMG[@alt='Post A Reply'][contains(@src,'sa-closed.jpg')]") ) {
   if ( selectSingleNode(doc, doc.getElementById("container"), "DIV[@class='threadbar bottom']/UL[@class='postbuttons']/LI/A/IMG[@alt='Reply'][contains(@src,'closed')]") ) {
      threadClosed = true;
   }
   //alert("threadClosed = "+threadClosed);

   //var resarray = new Array();
   //if (inFYAD) {
   //   resarray = selectNodes(doc, doc.body, "TABLE/TBODY[1]/TR[1]/TD[2]/TABLE[1]/TBODY[1]/TR[1]/TD[1]/TABLE[1]/TBODY[1]/TR[2]/TD[1]/DIV[1]/FONT[1]");
   //} else {
   //   resarray = selectNodes(doc, doc.body, "TABLE/TBODY[1]/TR[1]/TD[2]/TABLE[1]/TBODY[1]/TR[1]/TD[1]/TABLE[1]/TBODY[1]/TR[2]/TD[1]/DIV[@class='mainbodytextsmall']");
   //}
   // XXX: remove // when font tags are closed
   var resarray = selectNodes(doc, doc.getElementById("thread"), "TABLE[contains(@id,'post')]");
   var needUpdate = false;
   var needCssInsert = false;
   var updateTo = null;
   var updateLastPostID = null;
   var isEven = false;
   doc.postlinks = new Array;
   for (var x=0; x<resarray.length; x++) {
      if (!(resarray[x].className.match(/ignored/))) {
			  //var postdate = resarray[x].firstChild.nodeValue;
			  var postbarnode = selectSingleNode(doc, resarray[x], "TBODY/TR[@class='postbar']");
			  var userinfonode = selectSingleNode(doc, resarray[x], "TBODY/TR/TD[@class='userinfo']");
			  if (isEven) {
				 resarray[x].className += " salastread_even";
				 //postbarnode.className += " salastread_even";
			  } else {
				 resarray[x].className += " salastread_odd";
				 //postbarnode.className += " salastread_odd";
			  }
			  isEven = !isEven;
			  var postdatenode = selectSingleNode(doc, postbarnode, "TD[@class='postdate']");
			  if (postdatenode.firstChild.nodeName=="FONT") {
				 postdatenode = postdatenode.firstChild;
			  }
			  var postdate = postdatenode.lastChild.nodeValue;
			  
			  postdate = StripSpaces(postdate.substring(0, postdate.length));
			  //alert("postdate = "+postdate);
			  //try {
			  var posttime;
			  //if (inFYAD) {
			  //   posttime = StripSpaces(resarray[x].firstChild.nextSibling.firstChild.firstChild.nodeValue);
			  //} else {
			  //   posttime = StripSpaces(resarray[x].firstChild.nextSibling.firstChild.nodeValue);
			  //}
			  var pdmatch = postdate.match(/^(... \d\d, \d\d\d\d)\:? (\d\d\:\d\d)$/);
			  if (pdmatch) {
				  postdate = pdmatch[1];
				  posttime = pdmatch[2];
			  }
			  //} catch (e) { resarray[x].style.backgroundColor = "red"; throw e; }
			  var postdtvalue = ConvertLPDateTimeToNum(postdate, posttime);
			  var thisel = resarray[x];
			  //while ( thisel.nodeName != "TABLE" ) {
			  //   thisel = thisel.parentNode;
			  //}

			  var postid = 0;
			  //var postidlink = selectSingleNode(doc, thisel, "TBODY/TR[2]/TD[2]/TABLE/TBODY/TR[1]/TD[2]//A[contains(@href,'postid=')]");
			  //if (postidlink) {
			  //   var postidmatch = postidlink.href.match(/postid=(\d+)/);
			  //   postid = postidmatch[1];
			  //}
				  // XXX: The // in the next xpath can be changed to / when unclosed font tags stop messing with the forum DOM tree
			  var postlink = selectSingleNode(doc, postbarnode, "TD[@class='postdate']//A[contains(@href,'#')]").href;
			  postid = postlink.match(/post(\d+)/)[1];
			  //alert("postid = "+postid);

			  if (postid>0)
				 lpafter = postid;

			  //var ilpdt = IsLPDateTimeNew(false, postdtvalue, threadid, postid);
			  var ilpdt = (postid > lpbefore);
			  if ( ilpdt ) {
				 needUpdate = true;
				 updateTo = postdtvalue;
				 //var anchorval = selectNodes(doc, thisel, "TBODY/TR/TD/A[contains(@name,'post')]")[0];
				 //var avmatch = anchorval.name.match( /\d+/ );
				 //updateLastPostID = avmatch;
				 updateLastPostID = postid;
				 //if (inFYAD) {
				 //   setUnseenPostFYADColors(doc, thisel, "TBODY/TR/TD");
				 //} else {
					setUnseenPostColors(doc, thisel);
				 //}
			  } else {
				 //if (inFYAD) {
				 //   setSeenPostFYADColors(doc, thisel, "TBODY/TR/TD");
				 //} else {
					setSeenPostColors(doc, thisel);
				 //}
			  }
			  needCssInsert = true;
			  //alert("post colors set");

			  // Get classes...
			  var thiselClassNameAdd = "";
			  var posternodeClassNameAdd = "";
			  var posternodeparentClassNameAdd = "";
			  var rawpostername = "(unknown)";
			  var postername = "(unknown)";
			  var posteruserid = 0;
			  //var posteridnode = selectNodes(doc, thisel, "TBODY/TR[2]/TD[2]/TABLE/TBODY/TR[1]/TD[1]/DIV/A[contains(@href,'action=getinfo')]")[0];
			  //   The // can be / when font tags are closed
			  var posteridnode = selectSingleNode(doc, postbarnode, "TD[@class='postlinks']/UL[@class='profilelinks']/LI//A[contains(@href,'action=getinfo')]");
			  if (posteridnode) {
				 var idmatch = posteridnode.href.match(/userid=(\d+)/);
				 if (idmatch) {
					posteruserid = Number( idmatch[1] );
					thiselClassNameAdd += " somethingawfulforum_postbyid_"+posteruserid;
					posternodeClassNameAdd += " somethingawfulforum_usernameid_"+posteruserid;
				 }
			  }
			  //var posternode;
			  //if (inFYAD) {
			  //   posternode = selectNodes(doc, thisel, "TBODY/TR/TD/FONT/B")[0];
			  //} else {
			  //   posternode = selectNodes(doc, thisel, "TBODY/TR[1]/TD[1]/DIV/B")[0];
			  //}
			  var posternode = selectSingleNode(doc, thisel, "TBODY/TR/TD[@class='userinfo']/DL[@class='userinfo']/DT[@class='author']");
			  if (posternode) {
				 postername = posternode.firstChild.nodeValue;
				 if ( posternode.lastChild != posternode.firstChild )
				   postername = posternode.lastChild.nodeValue;
				   
				 if ( !postername ) { // to deal with radiums new name
				 	postername = posternode.childNodes[2].childNodes[0].nodeValue;
				 }
				 posterarray = postername.split(/&nbsp;/);
				 postername = posterarray.length == 1 ? posterarray[0] : posterarray[1];
				 rawpostername = postername;
				 postername = postername.replace(/[^A-Za-z0-9]/g,"_");
				 thiselClassNameAdd += " somethingawfulforum_postby_"+postername;
				 posternodeClassNameAdd += " somethingawfulforum_username_"+postername;
				 posternodeparentClassNameAdd += " somethingawfulforum_parentusername_"+postername;
			  }
			  if (!inFYAD) {
				 slurpIntoThreadCache(threadid);
				 if ( cachedThreadEntry && cachedThreadEntry.getAttribute("op")==posteruserid ) {
					thiselClassNameAdd += " somethingawfulforum_postbyOP";
					posternodeClassNameAdd += " somethingawfulforum_usernameOP";
					posternodeparentClassNameAdd += " somethingawfulforum_parentusernameOP";
				 }
				 //if ( SALR_IsModerator( posteruserid, forumid ) ) {
				var modcheck = selectSingleNode(doc, userinfonode, "DL[@class='userinfo']/DT[@class='author']/IMG[@title='Moderator']");
				if (modcheck && isloggedin) {
					thiselClassNameAdd += " somethingawfulforum_postbyMODERATOR";
					posternodeClassNameAdd += " somethingawfulforum_usernameMODERATOR";
					posternodeparentClassNameAdd += " somethingawfulforum_parentusernameMODERATOR";
				 }
				 //var admincheck = selectNodes(doc, thisel, "TBODY/TR[2]/TD[2]/TABLE/TBODY/TR[1]/TD[2]/DIV/A[contains(@href,'modalert.php')]")[0];
				 
				 //Checking for admins is harder than it used to be :argh:
				var admincheck = selectSingleNode(doc, postbarnode, "TD[@class='postlinks']/UL[@class='postbuttons']/LI/A/IMG[contains(@src,'report')]");
				// check for an admin star, make sure it isn't a mod star
				var admincheck2 = selectSingleNode(doc, posternode, "IMG[contains(@src,'http')]");
				var admincheck3 = selectSingleNode(doc, posternode, "IMG[contains(@src, 'moderator')]");
				 if (!admincheck && isloggedin) {
				    if (admincheck2 && !admincheck3) {
						thiselClassNameAdd += " somethingawfulforum_postbyADMIN";
						posternodeClassNameAdd += " somethingawfulforum_usernameADMIN";
						posternodeparentClassNameAdd += " somethingawfulforum_parentusernameADMIN";
					}
				 }
			  }

			  // Apply classes...
			  if (thiselClassNameAdd!="") {
				 thisel.className += thiselClassNameAdd;
			  }
			  if (posternode && posternodeClassNameAdd!="") {
				 posternode.className += posternodeClassNameAdd;
				 //if (persistObject.toggle_props) {
				 //   if (postername == "biznatchio") {
				 //      posternode.style.color = "red";
				 //   }
				 //}
			  }
			  if (posternode && posternodeparentClassNameAdd!="") {
				 posternode.parentNode.className += posternodeparentClassNameAdd;
			  }
			  //alert("classes applied");

			  //var titlenode = selectSingleNode(doc, thisel, "TBODY/TR[1]/TD[1]/DIV[3]");
		/*
			  var titlenode = selectSingleNode(doc, thisel, "DL[@class='userinfo']/DD[@class='title']");
			  if (titlenode) {
				 titlenode.className += " customtitle";
				 if ( persistObject.toggle_resizeCustomTitleText ) {
					var subnodes = selectNodes(doc, titlenode, ".//*");
					for (var i=0; i<subnodes.length; i++) {
					   if ( subnodes[i].style ) {
						  subnodes[i].style.fontSize = "8pt";
					   }
					}
				 }
			  }
		*/

			  if (persistObject.toggle_useQuickQuote && !threadClosed) {
				 //var quotebutton = selectNodes(doc, thisel, "//IMG[@alt='Reply w/Quote']")[0];
				 //   // to / when font tags are closed
				 var quotebutton = selectSingleNode(doc, postbarnode, "TD[@class='postlinks']/UL[@class='postbuttons']/LI//A/IMG[contains(@src,'quote')]");
				 if (quotebutton) {
					quotebutton.style.width = "12px !important";
					quotebutton.style.height = "20px !important";
					if(inBYOB){
						quotebutton.src = "chrome://salastread/content/byobarrow.gif";
					}else{
						quotebutton.src = "chrome://salastread/content/button-normalquote.gif";
					}
					quotebutton.alt = "Normal Reply w/Quote";

					var newquote = doc.createElement("IMG");
					if(inBYOB){
						newquote.src = "chrome://salastread/content/byob-qquote.gif";	
					}else{
						newquote.src = "chrome://salastread/content/button-quickquote.gif";
					}
					newquote.alt = "Quick Reply w/Quote";
					newquote.border = "0"
					newquote.style.cursor = "pointer";
					attachQuickQuoteHandler(threadid,doc,newquote,rawpostername,1,postid);
					quotebutton.parentNode.parentNode.insertBefore(newquote, quotebutton.parentNode);
					//quotebutton.onclick = function(evt) { return quickQuoteButtonClick(evt,threadid,doc,quotebutton,postername); };
				 }
				 var quotebutton = selectSingleNode(doc, postbarnode, "TD[@class='postlinks']/UL[@class='postbuttons']/LI//A/IMG[contains(@src,'edit')]");
				 if (quotebutton) {
					quotebutton.style.width = "12px !important";
					quotebutton.style.height = "20px !important";
					if(inBYOB){
						quotebutton.src = "chrome://salastread/content/byobarrow.gif";
					}else{
						quotebutton.src = "chrome://salastread/content/button-normaledit.gif";
					}
					quotebutton.alt = "Normal Reply w/Quote";

					var newquote = doc.createElement("IMG");
					if(inBYOB){
						newquote.src = "chrome://salastread/content/byob-qedit.gif";
					}else{
						newquote.src = "chrome://salastread/content/button-quickedit.gif";
					}
					newquote.alt = "Quick Reply w/Quote";
					newquote.border = "0"
					newquote.style.cursor = "pointer";
					newquote.is_edit = true;
					attachQuickQuoteHandler(threadid,doc,newquote,rawpostername,1,postid);
					quotebutton.parentNode.parentNode.insertBefore(newquote, quotebutton.parentNode);
					//quotebutton.onclick = function(evt) { return quickQuoteButtonClick(evt,threadid,doc,quotebutton,postername); };
				 }
			  }
			  //alert("qq set");

			  //if ( persistObject.toggle_fixBrokenQuotedLinks ) {
		/*
			  if ( 1==1 ) {
				 var bodylinknodes = selectNodes(doc, thisel, "TBODY/TR[1]/TD[2]/descendant::A");
				 for (var lnum=0; lnum<bodylinknodes.length; lnum++) {
					var href = bodylinknodes[lnum].href;
					if ( href.substring(href.length-8) == "%3C/a%3E" ) {
					   bodylinknodes[lnum].href = href.substring(0, href.length-8);
					} else {
					   //DEBUG:
					}
				 }
			  }
		*/

			  SALR_ProcessPostImages(thisel);
			  //alert("images processed");

			  if ( persistObject.toggle_insertPostTargetLink ||
				   persistObject.toggle_insertPostLastMarkLink ) {
				 if (postid!=0) {
					//var posttimenode;
					//if (inFYAD) {
					//   posttimenode = selectNodes(doc, thisel, "TBODY/TR[2]/TD[1]/DIV/FONT/FONT/B")[0];
					//} else {
					//   posttimenode = selectNodes(doc, thisel, "TBODY/TR[2]/TD[1]/DIV/B")[0];
					//}
					//  // to / when font tags are closed
					var posttimenode = selectSingleNode(doc, postbarnode, "TD[@class='postdate']//A");
		/*
					if (posttimenode && persistObject.toggle_insertPostTargetLink ) {
					   var plink = doc.createElement("A");
					   plink.href = "http://forums.somethingawful.com/showthread.php?s=&postid="+postid+"#post"+postid;
					   plink.title = "Link directly to this post";
					   plink.appendChild( doc.createTextNode("#") );
					   posttimenode.appendChild(doc.createTextNode(" "));
					   posttimenode.appendChild(plink);
					}
		*/
					if (posttimenode) {
					   var slink = doc.createElement("A");
					   slink.href = "http://forums.somethingawful.com/showthread.php?action=showpost&postid="+postid;
					   slink.title = "Show Single Post";
					   slink.appendChild( doc.createTextNode("1") );
					   posttimenode.parentNode.insertBefore(slink, posttimenode);
					   posttimenode.parentNode.insertBefore(doc.createTextNode(" "), posttimenode);
					}
					if (posttimenode && persistObject.toggle_insertPostLastMarkLink ) {
					   var plink = doc.createElement("A");
					   plink.href = "javascript:void('lr',"+postid+");";
					   plink.title = "Set \"Last Read\" post in this thread to this post";
					   plink.threadid = threadid;
					   plink.postid = postid;
					   plink.postdt = postdtvalue;
					   plink.parentpost = resarray[x];
					   plink.onclick = SALR_ChangeLastReadOnThread;
					   plink.appendChild( doc.createTextNode("<") );
					   doc.postlinks[doc.postlinks.length] = plink;
					   posttimenode.parentNode.insertBefore(plink, posttimenode);
					   posttimenode.parentNode.insertBefore(doc.createTextNode(" "), posttimenode);
					}
				 }
			  }
			  //alert("l inserted");

		/*
			  var postpane = selectSingleNode(doc, thisel, "TBODY[1]/TR[1]/TD[2]");

			  if (persistObject.toggle_removeTargetNewFromTorrentLinks) {
				 var tlinks = selectNodes(doc, postpane, "//A[contains(@href,'download.php?info_hash=')]");
				 for (var i=0; i<tlinks.length; i++) {
					tlinks[i].target = "";
				 }
			  }
		*/
      }
   } // End of main post loop

   if (needCssInsert) {
      var csstxt = SALR_MakeShowThreadCSS(doc);
      var sel = doc.createElement("style");
      sel.type = "text/css";
      sel.innerHTML = csstxt;
      doc.getElementsByTagName('head')[0].appendChild(sel);
   }
   if (needUpdate && !persistObject.toggle_scrollPostEnable) {
      UpdateLPDateTime(updateTo, threadid, updateLastPostID);
   }

   if (persistObject.toggle_useQuickQuote) {
      //var replybuttons = selectNodes(doc, doc.body, "//A[contains(@href,'newreply.php')]/IMG[@alt='Post A Reply'][contains(@src,'forum-reply')]");
      //var replybutton = selectSingleNode(doc, doc.body,
      //        "TABLE/TBODY[1]/TR[1]/TD[2]/TABLE[1]/TBODY[1]/TR[1]/TD[1]/TABLE[1]/TBODY[1]/TR[1]/TD[1]/TABLE[1]/TBODY[1]/TR[1]/TD[2]/DIV[1]/A[2][contains(@href,'newreply.php')]/IMG[@alt='Post A Reply'][contains(@src,'forum-reply')]"
      //);
      // XXX: // to / when fonts are closed
      var replybutton = selectSingleNode(doc, doc.getElementById("container"), "DIV[@class='threadbar top']/UL[@class='postbuttons']//LI//A/IMG[contains(@src,'reply')]");
      if (replybutton) {
         makeQuickReplyButton(threadid, doc, replybutton, inBYOB);
      }
      
      var postbuttons = selectNodes(doc, doc.body, "//IMG[@alt='Post']");
      if (postbuttons.length) {
        for (var uiego = 0; uiego < postbuttons.length; uiego++) {
          makeQuickPostButton(threadid, doc, postbuttons[uiego]);
        }
      }

      //replybutton = selectSingleNode(doc, doc.body,
      //    "TABLE/TBODY[1]/TR[1]/TD[2]/TABLE[1]/TBODY[1]/TR[1]/TD[1]/TABLE[1]/TBODY[1]/TR[1]/TD[2]/TABLE[1]/TBODY[1]/TR[1]/TD[4]/A[1][contains(@href,'newreply.php')]/IMG[@alt='Post A Reply'][contains(@src,'forum-reply')]"
      //);
      replybutton = selectSingleNode(doc, doc.getElementById("container"), "DIV[@class='threadbar bottom']/UL[@class='postbuttons']//LI//A/IMG[contains(@src,'reply')]");
      if (replybutton) {
      	   

         makeQuickReplyButton(threadid, doc, replybutton, inBYOB);
      }
   }

/*
   if (persistObject.toggle_thumbnailQuotedImagesInThreads) {
      var qimages = selectNodes(doc, doc.body, "//BLOCKQUOTE//IMG");
      for (var i=0; i<qimages.length; i++) {
         setupThumbnailImage(qimages[i],true,false);
      }
   }

   if (persistObject.toggle_removeTargetNewFromTorrentLinks) {
      var tlinks = selectNodes(doc, doc.body, "//A[contains(@href,'download.php?info_hash=')]");
      for (var i=0; i<tlinks.length; i++) {
         tlinks[i].target = "";
      }
   }
*/

   try {
      var isLastPage = SALR_SearchForThreadPages(doc);
      if (typeof(isLastPage)=="object" && isLastPage.res == true) {
         var pcount = ((isLastPage.num-1) * 40) + resarray.length - 1;
         //alert("looks like "+pcount+" posts up in this bitch");
         slurpIntoThreadCache(threadid);
         if ( cachedThreadEntry ) {
            cachedThreadEntry.setAttribute("lastreplyct", pcount);
         }
      }
   } catch (e) { }
   try { SALR_InsertThreadKeyboardNavigation(doc); } catch (e) { }

   reanchorThreadToLink(doc);
   
   doc.__salastread_loading = true;
   window.addEventListener("load", SALR_PageFinishedLoading, true);
   if (persistObject.toggle_scrollPostEnable)
     setTimeout(function () { SALR_CheckScrollPostPosition(doc); }, 1000);

   addInternalDebugLog("showthread.php handler, thread #"+threadid+", lpbefore="+lpbefore+", lpafter="+lpafter);
}

var specialDoc;

function SALR_PageFinishedLoading(e) {
  var doc = e.originalTarget;
  doc.__salastread_loading = false;
}

function SALR_CheckScrollPostPosition(doc) {
  if (doc.__salastread_processed) {
    var scrollpos = doc.defaultView.scrollY + doc.defaultView.innerHeight;
    var i;
    var a;
    for (i = 0; i < doc.postlinks.length; i++) {
      a = doc.postlinks[i];
      if (a.postid && (doc.__salastread_loading || !a.absolutepos)) 
        a.absolutepos = SALR_GetVerticalPos(a.parentpost);
      if (a.absolutepos && scrollpos > a.absolutepos) {
        SALR_SetNewLastReadIfLarger(a.threadid, a.postdt, a.postid);
      }
    }
  setTimeout(function () { SALR_CheckScrollPostPosition(doc); }, 5000);
  }
}

function SALR_SetNewLastReadIfLarger(threadid, postdt, postid) {
   slurpIntoThreadCache(threadid);
   if (cachedThreadEntry) {
      var lastdt = cachedThreadEntry.getBypassAttribute("lastpostdt");
      if (lastdt && postdt > lastdt) {
        cachedThreadEntry.setAttribute("lastpostdt", postdt);
        cachedThreadEntry.setAttribute("lastpostid", postid);
        //persistObject.SaveXML();
         var threaddetails = new Array();
         threaddetails['id'] = threadid;
         threaddetails['lastpostdt'] = postdt;
         threaddetails['lastpostid'] = postid;
         persistObject.SavePostDataSQL(threaddetails);
      }
    }
}

function SALR_GetVerticalPos(element) {
  //var x = 0;
  var y = 0;
  var p = element;
  while (p) {
    //x += p.offsetLeft;
    y += p.offsetTop;
    p = p.offsetParent;
    }
  return y;
}


function SALR_InsertThreadKeyboardNavigation(doc) {
   // XXX: temporarily disabled
   return;
   doc.onkeypress = function(e) {
      if (e.which==32)
      {
         var curTop = doc.body.scrollTop;
         setTimeout(function() { SALR_CheckForSpaceScroll(doc, curTop); }, 50);
      }
   }
}

function SALR_CheckForSpaceScroll(doc, oldTop) {
   var newTop = doc.body.scrollTop;
   if (oldTop==newTop) {
      var bclassmatch = doc.body.className.match(/salastread_thread_(\d+)/);
      if (bclassmatch) { 
         var curPage = doc._SALR_curPage;
         var maxPages = doc._SALR_maxPages;
         var threadid = Number(bclassmatch[1]);
         if (maxPages>curPage) {
            doc.location = "http://forums.somethingawful.com/showthread.php?s=&threadid="+threadid+"&pagenumber="+(curPage+1);
            return;
         }
         slurpIntoThreadCache(threadid);
         if (cachedThreadEntry) {
            var postid = cachedThreadEntry.getBypassAttribute("lastpostid");
            if (postid)
            {
               var nurl = "http://forums.somethingawful.com/showthread.php?s=&postid="+postid+"#post"+postid;
               if (doc.location.href == nurl)
                  doc.location.reload();
               else
                  doc.location = nurl;
            }
         }
      }
   }
}

function SALR_DirectionalNavigate(doc, dir) {
   if (dir == "top") {
      var tforum = doc.__SALR_forumid;
      doc.location = "http://forums.somethingawful.com/forumdisplay.php?s=&forumid="+tforum;
   }
   else if (dir == "left") {
      var curPage = doc.__SALR_curPage;
      if (curPage > 1) {
         var threadid = doc.__SALR_threadid;
         doc.location = "http://forums.somethingawful.com/showthread.php?s=&threadid="+threadid+"&perpage=40&pagenumber="+(curPage-1);
      }
   }
   else if (dir == "right") {
      var curPage = doc.__SALR_curPage;
      var maxPage = doc.__SALR_maxPage;
      if (maxPage > curPage) {
         var threadid = doc.__SALR_threadid;
         doc.location = "http://forums.somethingawful.com/showthread.php?s=&threadid="+threadid+"&perpage=40&pagenumber="+(curPage+1);
      }
   }
}

function SALR_PageMouseUp(event) {
   var targ = event.target;
   var doc = targ.ownerDocument;
   if (targ && targ.SALR_isGestureElement==true) {
      doc.body.addEventListener('contextmenu', SALR_GestureContextMenu, false);
      SALR_DirectionalNavigate(doc, targ.SALR_dir);
      //alert("dir="+targ.SALR_dir);
   }

   var gn = doc.getElementById("salastread_gesturenavtop");
   if (gn) {
      var rx = function(dir) {
         var el = doc.getElementById("salastread_gesturenav"+dir);
         el.parentNode.removeChild(el);
      }
      rx("top");
      rx("left");
      rx("right");
      rx("bottom");
   }
}

function SALR_GestureContextMenu(event) {
   var targ = event.target;
   var doc = targ.ownerDocument;
   doc.body.removeEventListener('contextmenu', SALR_GestureContextMenu, false);
   if (event.preventDefault) {
      event.preventDefault();
   }
   return false;
}

function SALR_PageMouseDown(event) {
   var doc = event.target.ownerDocument;
   var gn = doc.getElementById("salastread_gesturenavtop");
   if (gn) {
      return;
   }
   if (event.button == persistObject.int_gestureButton && persistObject.toggle_gestureEnable) {
      var cx = function(dir, ofsy, ofsx) {
         var el = doc.createElement("IMG");
         el.SALR_dir = ""+dir;
         el.id = "salastread_gesturenav"+dir;
         el.className = "salastread_gesturenav";
         el.src = "chrome://salastread/content/gesturenav-"+dir+".png";
         el.style.left = ((event.clientX - 36) + (77 * ofsx)) + "px";
         el.style.top = ((event.clientY - 36) + (77 * ofsy)) + "px";
         doc.body.appendChild(el);
         el.SALR_isGestureElement = true;
         if (dir=="left" && doc.__SALR_curPage <= 1) {
            el.className += " disab";
         }
         else if (dir=="right" && doc.__SALR_maxPage <= doc.__SALR_curPage) {
            el.className += " disab";
         }
      };
      cx("top", -1, 0);
      cx("left", 0, -1);
      cx("right", 0, 1);
      cx("bottom", 1, 0);
   }
}

function SALR_SearchForThreadPages(doc) {
   if (!persistObject.toggle_enablePageNavigator)
      return { res: false };

   doc.body.addEventListener('mousedown', SALR_PageMouseDown, false);
   doc.body.addEventListener('mouseup', SALR_PageMouseUp, false);
   //doc.body.addEventListener('contextmenu', SALR_GestureContextMenu, false);

   var rval = { res: true, num: 1 };
   //var pel = selectSingleNode(doc, doc.body, "TABLE/TBODY/TR/TD/TABLE[1]/TBODY/TR/TD/DIV[@class='mainbodytext']/B[1]/A[@class='pagenumber']");
   var pel = selectSingleNode(doc, doc.getElementById("container"), "DIV[@class='pages top']/B/A[@class='pagenumber']");
   if (pel) {
      //alert("found pel");
      var turl = pel.href;
      var boldel = pel.parentNode;
      pel = pel.parentNode.parentNode;
      var peltext = pel.innerHTML;
      var pcountmatch = peltext.match(/\((\d+)\):/);
      if (pcountmatch) {
         var maxPages = Number(pcountmatch[1]);
         //alert("I found "+maxPages+" pages.");

         for (var i=0; i<boldel.childNodes.length; i++) {
            var thisChild = boldel.childNodes[i];
            if (thisChild.nodeName=="#text") {
               var nmatch = thisChild.nodeValue.match(/(\d+)/);
               if (nmatch) {
                  var curPage = Number(nmatch[1]);
                  //alert("current page is "+nmatch[1]);

                  var navDiv = doc.createElement("DIV");
                  navDiv.className = "salastread_pagenavigator";
                  //navDiv.style.position = "fixed";
                  //navDiv.style.right = "0px";
                  //navDiv.style.bottom = "0px";
                  //navDiv.style.backgroundColor = "#ddd";
                  //navDiv.style.padding = "4px 4px 4px 4px";

                  var firstBtn = doc.createElement("IMG");
                  firstBtn.src = "chrome://salastread/content/nav-firstpage.png";
                  firstBtn.title = "Go to First Page";
                  //firstBtn.appendChild(doc.createTextNode("<<"));
                  //firstBtn.appendChild(firstPageImg);
                  if (curPage==1) {
                     //firstBtn.disabled = true;
                     firstBtn.className = "disab";
                  } else {
                     firstBtn.onclick = function() { doc.location = turl.replace(/pagenumber=(\d+)/, "pagenumber=1"); };
                  }

                  var prevBtn = doc.createElement("IMG");
                  prevBtn.src = "chrome://salastread/content/nav-prevpage.png";
                  prevBtn.title = "Go to Previous Page";
                  if (curPage==1) {
                     //prevBtn.disabled = true;
                     prevBtn.className = "disab";
                  } else {
                     prevBtn.onclick = function() { doc.location = turl.replace(/pagenumber=(\d+)/, "pagenumber="+(curPage-1)); };
                  }

                  doc.__SALR_curPage = curPage;
                  doc.__SALR_maxPage = maxPages;

                  var pageSel = doc.createElement("SELECT");
                  pageSel.size = 1;
                  for (var pp=1; pp<=maxPages; pp++)
                  {
                     var topt = doc.createElement("OPTION");
                     topt.appendChild(doc.createTextNode(pp));
                     if (pp==curPage) topt.selected = true;
                     pageSel.appendChild(topt);
                  }
                  pageSel.onchange = function() { doc.location = turl.replace(/pagenumber=(\d+)/, "pagenumber="+(Number(pageSel.selectedIndex)+1)); };

                  var nextBtn = doc.createElement("IMG");
                  nextBtn.src = "chrome://salastread/content/nav-nextpage.png";
                  nextBtn.title = "Go to Next Page";
                  if (curPage==maxPages) {
                     //nextBtn.disabled = true;
                     nextBtn.className = "disab";
                     rval.res = true;
                     rval.num = curPage;
                  } else {
                     nextBtn.onclick = function() { doc.location = turl.replace(/pagenumber=(\d+)/, "pagenumber="+(curPage+1)); };
                  }

                  var lastBtn = doc.createElement("IMG");
                  lastBtn.src = "chrome://salastread/content/nav-lastpage.png";
                  lastBtn.title = "Go to Last Page";
                  if (curPage==maxPages) {
                     //lastBtn.disabled = true;
                     lastBtn.className = "disab";
                  } else {
                     lastBtn.onclick = function() { doc.location = turl.replace(/pagenumber=(\d+)/, "pagenumber="+maxPages); };
                  }

                  navDiv.appendChild(firstBtn);
                  navDiv.appendChild(prevBtn);
                  navDiv.appendChild(pageSel);
                  navDiv.appendChild(nextBtn);
                  navDiv.appendChild(lastBtn);
                  doc.body.appendChild(navDiv);

                  var ss = doc.createElement("link");
                  ss.rel = "stylesheet";
                  ss.href = "chrome://salastread/content/pagenavigator-content.css";
                  doc.getElementsByTagName('head')[0].appendChild(ss);

                  doc._SALR_curPage = curPage;
                  doc._SALR_maxPages = maxPages;

                  break;
               }
            }
         }
      }
   }
   return rval;
}

var modCheckCache = null;

function SALR_IsModerator(userid, forumid) {
   if ( persistObject.forumListXml ) {
      var mList = null;
      if ( modCheckCache && modCheckCache[0]==forumid ) {
         mList = modCheckCache[1];
      } else {
         var forumNode = selectSingleNode( persistObject.forumListXml, persistObject.forumListXml, "//forum[@id='"+forumid+"']");
         if ( forumNode && forumNode.hasAttribute("mods") ) {
            mList = forumNode.getAttribute("mods").split(",");
         }
         if ( forumNode && forumNode.hasAttribute("modnames") ) {
            var mnList = forumNode.getAttribute("modnames").split(",");
            for (var i=0; i<mnList.length; i++) {
               mList.push(mnList[i]);
            }
         }
         modCheckCache = new Array(2);
         modCheckCache[0] = forumid;
         modCheckCache[1] = mList;
      }
      if ( mList ) {
         for (var i=0; i<mList.length; i++) {
            if (mList[i]==userid) {
               return true;
            }
         }
      }
   }
   return false;
}

function SALR_ChangeLastReadOnThread(e) {
   slurpIntoThreadCache(e.originalTarget.threadid);
   if (cachedThreadEntry) {
      cachedThreadEntry.setAttribute("lastpostdt", e.originalTarget.postdt);
      cachedThreadEntry.setAttribute("lastpostid", e.originalTarget.postid);
      //persistObject.SaveXML();
      var threaddetails = new Array();
      threaddetails['id'] = threadid;
      threaddetails['lastpostdt'] = e.originalTarget.postdt;
      threaddetails['lastpostid'] = e.originalTarget.postid;
      persistObject.SavePostDataSQL(threaddetails);

      var doc = e.originalTarget.ownerDocument;
      var notel = doc.createElement("DIV");
      notel.appendChild(doc.createTextNode("Last Post reset to this post."));
      notel.style.position = "absolute";
      notel.style.border = "1px solid black";
      notel.style.backgroundColor = "yellow";
      notel.style.color = "black";
      notel.style.padding = "2px 2px 2px 2px";
      notel.style.fontFamily = "Tahoma, Arial, Helvetica, sans-serif";
      notel.style.fontSize = "small";
      var lef = 0;
      var top = 0;
      var tel = e.originalTarget;
      while (tel) {
         lef += tel.offsetLeft;
         top += tel.offsetTop;
         tel = tel.offsetParent;
      }
      notel.style.top = (top + e.originalTarget.offsetHeight) + "px";
      notel.style.left = lef + "px";
      notel.opacity = 100;
      doc.body.appendChild(notel);
      setTimeout( function() { SALR_NoteFade(notel); }, 1000 );
   }
}

function SALR_NoteFade(targetEl) {
   targetEl.opacity -= 5;
   targetEl.style.MozOpacity = (targetEl.opacity / 100);
   if (targetEl.opacity > 5) {
      setTimeout( function() { SALR_NoteFade(targetEl); }, 10 );
   } else {
      targetEl.parentNode.removeChild(targetEl);
   }
}

function makeQuickReplyButton(threadid,doc,replybutton, inBYOB) {

    
   replybutton.style.width = "12px !important";
   replybutton.style.height = "20px !important";
   if(inBYOB){
   	replybutton.src = "chrome://salastread/content/byobarrow.gif";
   }else{
   	replybutton.src = "chrome://salastread/content/button-normalreply.gif";
   }
   replybutton.alt = "Normal Reply";

   var newreply = doc.createElement("IMG");
   if(inBYOB){
   	newreply.src = "chrome://salastread/content/byob-qreply.gif";
   }else{
   	newreply.src = "chrome://salastread/content/button-quickreply.gif";
   }
   newreply.alt = "Quick Reply";
   newreply.border = "0"
   newreply.style.cursor = "pointer";
   newreply.SALR_threadid = threadid;
   attachQuickQuoteHandler(threadid,doc,newreply,"",0);
   replybutton.parentNode.parentNode.insertBefore(newreply, replybutton.parentNode);
}

function makeQuickPostButton(threadid,doc,replybutton) {
   var forumid = replybutton.parentNode.href.match(/forumid=[0-9]+/);
   if (forumid.length) forumid = forumid[0].split(/=/);
   if (forumid.length) forumid = forumid[1];
   else return;

   replybutton.style.width = "12px !important";
   replybutton.style.height = "20px !important";
   if(forumid== 174){
   	replybutton.src = "chrome://salastread/content/byobarrow.gif";
   }else{
   	replybutton.src = "chrome://salastread/content/button-normalpost.gif";
   }
   replybutton.alt = "Normal Post";

   var newreply = doc.createElement("IMG");
   if(forumid== 174){
      	newreply.src = "chrome://salastread/content/byob-qpost.gif";
   }else{
   	newreply.src = "chrome://salastread/content/button-quickpost.gif";
   }
   newreply.alt = "Quick Post";
   newreply.border = "0"
   newreply.style.cursor = "pointer";
   newreply.SALR_threadid = undefined;
   newreply.SALR_forumid = forumid;
   attachQuickQuoteHandler(undefined,doc,newreply,"",0);
   replybutton.parentNode.parentNode.insertBefore(newreply, replybutton.parentNode);
}

function setupThumbnailImage(img,isquoted,istti) {
   img.__fullsize = false;
   img.__salastread_isquoted = isquoted;
   img.__salastread_texttoimage = istti;
   setImageThumbnailSize(img,false);
   if ( !img.__salastread_resizeattached==true ) {
      img.addEventListener("resize", setImageThumbnailSizeNonToggle, true);
      img.addEventListener("load", setImageThumbnailSizeNonToggleL, true);
      img.addEventListener("click", setImageThumbnailSizeToggle, true);
      //img.addEventListener("resize", function() { setImageThumbnailSize(img,false); }, true);
      //img.addEventListener("load", function() { setImageThumbnailSize(img,false); }, true);
      //img.addEventListener("click", function() { setImageThumbnailSize(img,true); }, true);
      img.__salastread_resizeattached = true;
   }
}

var imgresize_recurseprotect = 0;

function setImageThumbnailSizeNonToggleL(evt) {
   var img = evt.currentTarget;
   //alert("load "+img);
   setImageThumbnailSize(img, false);
}

function setImageThumbnailSizeNonToggle(evt) {
   var img = evt.originalTarget;
   setImageThumbnailSize(img, false);
}

function setImageThumbnailSizeToggle(evt) {
   var img = evt.originalTarget;
   setImageThumbnailSize(img, true);
}

function setImageThumbnailSize(img,fullsizetoggle) {
   if (imgresize_recurseprotect==0) {
      imgresize_recurseprotect = 1;
      if (fullsizetoggle) {
         img.__fullsize = !img.__fullsize;
      }
      var maxwidth = 150;
      var widthonly = 0;
      if ( img.__salastread_texttoimage==true && img.__salastread_isquoted==false ) {
         maxwidth = 600;
         widthonly = 1;
      }
      var scalepct = maxwidth/img.naturalWidth;
      if ( widthonly!=1 && maxwidth/img.naturalHeight < scalepct ) {
         scalepct = maxwidth/img.naturalHeight;
      }
      if (scalepct < 1) {
         if (img.__fullsize==true) {
            scalepct = 1;
         }
         img.style.width = Math.floor( img.naturalWidth * scalepct ) + "px";
         img.style.height = Math.floor( img.naturalHeight * scalepct ) + "px";
      }
      imgresize_recurseprotect = 0;
   }
}

function reanchorThreadToLink(doc) {

   if ( persistObject.toggle_reanchorThreadOnLoad ) {

      var hashmatch = doc.location.href.match(/\#(.*)$/);
      if (hashmatch) {
         var anchorNode = selectNodes(doc, doc.body, "//table[@id='"+hashmatch[1]+"']")[0];
         if (anchorNode) {
            anchorNode.scrollIntoView(true);
         }
      }
   }
}

function SALR_runConfig(page) {
   //var doc = e.originalTarget;
   //doc.location = "chrome://salastread/content/configuration.html";
   var data = "";
   if (typeof(page)=="string") {
      data = page;
   }
   openDialog("chrome://salastread/content/pref.xul","_blank",
              "chrome,titlebar,modal,resizable", data);
}

function handleEditPost(e) {
   var doc = e.originalTarget;
   var submitbtn = selectNodes(doc, doc.body, "//INPUT[@type='submit'][@value='Save Changes']")[0];
   var tarea = selectNodes(doc, doc.body, "//TEXTAREA[@name='message']")[0];
   if (submitbtn && tarea) {
      submitbtn.addEventListener("click", function() { parsePLTagsInEdit(tarea); }, true);
      submitbtn.style.backgroundColor = persistObject.color_postedInThreadRe;
   }
}

var salastread_needRegReplyFill = false;

function setRegReplyFillOn() {
   salastread_needRegReplyFill = true;
}

function handleNewReply(e) {
   var doc = e.originalTarget;
   var threadlink = selectSingleNode(doc, doc.body, "DIV[contains(@id, 'container')]/TABLE[1]/TBODY[1]/TR[1]/TD[1]/SPAN[1]/B/A[contains(@href,'showthread.php')][contains(@href,'threadid=')]");
   if (threadlink) {
      var tlmatch = threadlink.href.match( /threadid=(\d+)/ );
      if ( tlmatch ) {
         var threadid = tlmatch[1];
         if ( salastread_needRegReplyFill ) {
            var msgEl = selectSingleNode(doc, doc.body, "//TEXTAREA[@name='message']");
            if (msgEl) {
               msgEl.value = salastread_savedQuickReply;
            }
            salastread_needRegReplyFill = false;
         }
         var postbtn = selectNodes(doc, doc.body, "//FORM[@name='vbform'][contains(@action,'newreply.php')]//INPUT[@type='submit'][@name='submit']")[0];
         if (postbtn) {
            postbtn.addEventListener("click", function() { markThreadReplied(persistObject, threadid); }, true);
            postbtn.style.backgroundColor = persistObject.color_postedInThreadRe;
         }
      }
   } else {
      if (salastread_savedQuickReply!="") {
         var forgeCheck = selectSingleNode(doc, doc.body, "TABLE/TBODY[1]/TR[1]/TD[1]/TABLE[1]/TBODY[1]/TR[1]/TD[1]/TABLE[1]/TBODY[1]/TR[2]/TD[1]/FONT[contains(text(),'have been forged')]");
         if (forgeCheck) {
            persistObject.__cachedFormKey = "";
            var reqMsg = doc.createElement("P");
            reqMsg.style.fontFamily = "Verdana, Arial, Helvetica";
            reqMsg.style.fontSize = "80%";
            reqMsg.style.backgroundColor = "#fcfd99";
            reqMsg.style.border = "1px solid black";
            reqMsg.style.padding = "2px 2px 2px 2px";
            reqMsg.appendChild(
               doc.createTextNode("Message from SA Last Read: " +
                  "Quick Reply appears to have worked incorrectly. To open "+
                  "your reply in a regular forum reply page, click ")
            );
            var regReplyLink = doc.createElement("A");
            regReplyLink.onclick = setRegReplyFillOn;
            regReplyLink.href = "http://forums.somethingawful.com/newreply.php?s=&action=newreply&threadid=" +
               salastread_savedQuickReplyThreadId;
            regReplyLink.appendChild(doc.createTextNode("here."));
            reqMsg.appendChild(regReplyLink);
            forgeCheck.parentNode.insertBefore(reqMsg, forgeCheck);
         } else {
            salastread_savedQuickReply = "";
            salastread_savedQuickReplyThreadId = "";
         }
      }
   }
}

function markThreadReplied(pobj, threadid) {
   var xmlDoc = pobj.xmlDoc;
   var threads = selectNodes(xmlDoc, xmlDoc, "/salastread/thread[@id='"+threadid+"']");
   for (var i=0; i<threads.length; i++) {
      threads[i].setAttribute("posted","1");
   }
   invalidateThreadCache();
   //pobj.SaveXML();
   var threaddetails = new Array();
   threaddetails['id'] = threadid;
   threaddetails['posted'] = 1;
   persistObject.SavePostDataSQL(threaddetails);
}

function handleConfigLinkInsertion(e) {
   var doc = e.originalTarget;
   var usercpnode = selectSingleNode(doc, doc.body, "//A[@class='pagenumbersmall'][contains(@href,'usercp.php?s=')]");
   if (usercpnode) {
      var sep = doc.createTextNode(" - ");
      var newlink = doc.createElement("A");
      newlink.appendChild( doc.createTextNode("Configure Last Read Extension") );
      usercpnode.parentNode.insertBefore(newlink, usercpnode.nextSibling);
      usercpnode.parentNode.insertBefore(sep, newlink);
      newlink.href = "#";
      //newlink.href = "chrome://salastread/content/configuration.html";
      newlink.className = "pagenumbersmall";
      //newlink.onclick = function() { runConfig(e); };
      newlink.addEventListener("click", SALR_runConfig, true);
      //newlink.onclick = runConfig;
      return 1;
   } else {
      return 0;
   }
}

function salastread_addUpdateIcon(doc) {
   if ( persistObject._updateURL != "" ) {
      var updlink = doc.createElement("A");
      var updicon = doc.createElement("IMG");
      updlink.href = persistObject._updateURL;
      if ( persistObject._killed==true ) {
         updicon.src = "chrome://salastread/content/killedicon.png";
         updicon.title = "SA Last Read Update REQUIRED";
      } else {
         updicon.src = "chrome://salastread/content/updateicon.png";
         updicon.title = "SA Last Read Update Available";
      }
      updicon.style.width = "35px";
      updicon.style.height = "33px";
      updicon.style.border = "none";
      updlink.appendChild(updicon);
      updlink.style.display = "block";
      updlink.style.position = "fixed";
      updlink.style.right = "5px";
      updlink.style.bottom = "5px";
      doc.body.appendChild(updlink);
   }
}

function handleBodyClassing(e) {
   var doc = e.originalTarget;
   var docbody = doc.body;
   var addclass = " somethingawfulforum";
   var phmatch = doc.location.href.match( /\/([^\/]*)\.php/ );
   if (phmatch) {
      addclass += " somethingawfulforum_"+phmatch[1]+"_php";
   }
   docbody.className += addclass;
}

/*
function __TEST__hookupTitleChanged() {
   document.getElementById("content").addEventListener("DOMTitleChanged", __TEST__salastread_titleChanged, false);
}

var checkForCopyrightFailCount = 0;

function __TEST__salastread_titleChanged(event) {
   var loc = event.target.location;
   if ( loc.href.match(/^http:\/\/forums\.somethingawful\.com\//i) ) {
      var fakee = {
         originalTarget: event.target
      };
      //setTimeout( function() { salastread_windowOnLoad(fakee); }, 50 );
      checkForCopyrightFailCount = 0;
      setTimeout( function() { __TEST__docloaded(fakee); }, 50 );
   }
}

function __TEST__docloaded(e) {
   var doc = e.originalTarget;
   try {
      // copyright notice at bottom of page is the only <p> in the main body of a forum page
      //var copyrightnotice = selectNodes(doc, doc.body, "P/FONT")[0];
      
      var commentnodes = selectNodes(doc, doc.body, "child::comment()");
      var count=0;
      for (var i=0; i<commentnodes.length; i++) {
         var cn = commentnodes[i];
         if (cn.nodeValue.match(/End ad\-free/)) {
            count++;
         }
      }
      //if (count>0) { alert("count = "+count); return; }
      if (count==2) {
         salastread_windowOnLoad(e);
         return;
      }
   }
   catch (err) {
   }
   checkForCopyrightFailCount++;
   if (checkForCopyrightFailCount < 5) {
      setTimeout( function() { __TEST__docloaded(e); }, 50 );
   }
   else if (checkForCopyrightFailCount < 10) {
      setTimeout( function() { __TEST__docloaded(e); }, 250 );
   }
   else {
      //alert("salastread: t-t-t-t-t-t-TOTAL FAILURE!");
   }
}
*/

function salastread_hidePageHeader(doc) {
   var hiddenElements = new Array();
   var hideEl = function(id) {
      var el;
      if (typeof id == "string") {
         el = doc.getElementById(id);
      } else {
         el = id;
      }
      if (el) {
         el.SALR_display = el.style.display;
         el.style.display = "none";
         hiddenElements.push(el);
      }
   }

   hideEl("globalmenu");
   hideEl("searchboxes");
   hideEl("navigation");
   var nav = doc.getElementById("navigation");
   if (nav) {
      nav = nav.nextSibling;
      if (nav && nav.nodeName != "DIV") {
         nav = nav.nextSibling;
      }
      if (nav && selectSingleNode(doc, nav, "A[@target='_new']/IMG")) {
         hideEl(nav);
      }
   }
   hideEl("copyright");
   var copyright = doc.getElementById("copyright");
   if (copyright) {
      if (copyright) copyright = copyright.previousSibling;
      if (copyright && copyright.nodeName != "DIV") copyright = copyright.previousSibling;
      if (copyright && selectSingleNode(doc, copyright, "A[@target='_new']/IMG")) {
         hideEl(copyright);
      }
   }

   if (hiddenElements.length > 0) {
      var togLink = doc.createElement("DIV");
      togLink.className = "salastread_showhideheaderbutton";
      togLink.appendChild(doc.createTextNode("[Show Header/Footer]"));
      togLink.onclick = function() {
         for (var i=0; i<hiddenElements.length; i++) {
            var tel = hiddenElements[i];
            tel.style.display = tel.SALR_display;
         }
         togLink.style.display = "none";
         return false;
      };
      doc.body.appendChild(togLink);

      var lr = doc.createElement("link");
      lr.rel = "stylesheet";
      lr.type = "text/css";
      lr.href = "chrome://salastread/content/hideshowheaderbutton.css";
      doc.getElementsByTagName('head')[0].appendChild(lr);
   }
}

function salastread_hidePageHeader_OLD(doc) {
   var showToggleLink = false;
   var oldDisplay = new Array();
   var showElements = new Array();
   var searchTable = selectSingleNode(doc, doc.body, "TABLE[1]");
   if (searchTable && searchTable.innerHTML.match(/Search Google/)) {
      oldDisplay.push(searchTable.style.display);
      searchTable.style.display = "none";
      showToggleLink = true;
      showElements.push(searchTable);
   }
   //var linksTable = selectSingleNode(doc, doc.body, "TABLE[2]");
   var linksTable = selectSingleNode(doc, doc.body, "DIV[1][@id='globalthing']");
   //if (linksTable && linksTable.innerHTML.match(/Something Awful Website/)) {
   if (linksTable) {
      oldDisplay.push(linksTable.style.display);
      linksTable.style.display = "none";
      showToggleLink = true;
      showElements.push(linksTable);
   }
   var adDiv = selectSingleNode(doc, doc.body, "DIV[1]");
   if (adDiv && adDiv.innerHTML.match(/zipa.com/)) {
      oldDisplay.push(adDiv.style.display);
      adDiv.style.display = "none";
      showToggleLink = true;
      showElements.push(adDiv);
   }

   var centerEls = selectNodes(doc, doc.body, "CENTER");
   for (var cn=centerEls.length-1; cn>=0; cn--) {
      if (centerEls[cn].innerHTML.match(/bannerads/)) {
         oldDisplay.push(centerEls[cn].style.display);
         centerEls[cn].style.display = "none";
         showToggleLink = true;
         showElements.push(centerEls[cn]);
         cn = 0;
      }
   }
   var divEls = selectNodes(doc, doc.body, "DIV");
   for (var dn=divEls.length-1; dn>=0; dn--) {
      var dstr = divEls[dn].innerHTML;
      if (dstr.match(/Jelsoft Enterprises/) && !dstr.match(/Comedy Gas Chamber/)) {
         oldDisplay.push(divEls[dn].style.display);
         divEls[dn].style.display = "none";
         showToggleLink = true;
         showElements.push(divEls[dn]);
         dn = 0;
      }
   }


   if (showToggleLink) {
      var togLink = doc.createElement("DIV");
      togLink.appendChild(doc.createTextNode("[Show Header/Footer]"));
      togLink.style.position = "absolute";
      togLink.style.top = "0px";
      togLink.style.right = "0px";
      togLink.style.fontFamily = "Tahoma, Arial, Helvetica, sans-serif";
      togLink.style.fontSize = "8.5pt";
      togLink.style.fontWeight = "bold";
      togLink.style.padding = "2px";
      togLink.style.margin = "3px";
      togLink.style.display = "block";
      togLink.style.cursor = "pointer";
      togLink.style.border = "2px outset rgb(0,102,153)";
      togLink.style.backgroundColor = "rgb(0,102,153)";
      togLink.style.color = "rgb(255,255,255)";
      togLink.style.zIndex = "1000";
      togLink.onclick = function() {
         for (var i=0; i<showElements.length; i++) {
            showElements[i].style.display = oldDisplay[i];
         }
         togLink.style.display = "none";
         return false;
      };
      doc.body.appendChild(togLink);
   }
}

function SALR_ParamsToUrl(params) {
   var res = "";
   for (var key in params) {
      if (key.indexOf("salr_")==0) {
         res += "&" + escape(key) + "=" + escape(params[key]);
      }
   }
   return res;
}

var SALR_ProfileUserName;

function SALR_HandleProfileInsertion(e) {
   try
   {
      var doc = e.originalTarget;
      var location = doc.location;

      var params = new Object();

      var qstring = location.search;
      if (qstring.substr(0,1)=="?")
         qstring = qstring.substr(1);
      var qsplit = qstring.split("&");
      for (var qn=0; qn<qsplit.length; qn++) {
         var qparams = qsplit[qn].split("=");
         var qname = unescape(qparams[0]);
         var qvalue = unescape(qparams[1]);
         params[qname] = qvalue;
      }

      var capImg = doc.getElementById("captcha");

      if ( capImg && params["salr_addprofilekey"] && params["action"]=="editprofile" ) {
         var ihtmlm = doc.body.innerHTML.match(/">User Control Panel For (.*?)<\/a>/);
         if (!ihtmlm) return;
         SALR_ProfileUserName = ihtmlm[1];
         setTimeout(function() {
            var data = new Object();
            data["captchaUrl"] = capImg.src;
            openDialog("chrome://salastread/content/profileEditConfirm.xul","_blank",
                       "chrome,titlebar,modal,resizable", data);
            if (data["continue"]) {
               var formtag = selectSingleNode(doc, doc.body, "//form[@action='member.php']");
               var captext = selectSingleNode(doc, doc.body, "//input[@name='captcha']");
               var f1 = selectSingleNode(doc, doc.body, "//input[@name='field1']");
               if (formtag && captext && f1) {
                  f1.value = "SALR["+ params["salr_addprofilekey"] +"]";
                  formtag.action = "member.php?salr_profileinsertcontinue=true" + SALR_ParamsToUrl(params);
                  captext.value = data["captchaText"];
                  formtag.submit();
               }
            }
         },1);
         return;
      }
      else if ( params["salr_profileinsertcontinue"]=="true" ) {
         if (doc.body.innerHTML.indexOf("hank you for")!=-1) {
            // Success!!
            alert("Profile successfully updated");
            if (params["salr_onsuccessurl"]) {
               var surl = params["salr_onsuccessurl"];
               if (surl.indexOf("?")!=-1)
                  surl += "&";
               else
                  surl += "?";
               surl += "salr_username=" + SALR_ProfileUserName;
               doc.location = surl;
            }
         } else {
            if (confirm("Your profile did not update correctly. (You may have entered an incorrect validation code.) "+
                        "Press OK to try again.")) {
               doc.location = "http://forums.somethingawful.com/member.php?s=&action=editprofile"+SALR_ParamsToUrl(params);
            }
         }
      }
   } catch (err) { }
}

function SALR_windowOnLoadMini(e) {
   var doc = e.originalTarget;
   var location = doc.location;
   try {
      if (doc.__salastread_processed) {
         if ( persistObject.toggle_reanchorThreadOnLoad ) {
            var samatch = location.href.match( /^http:\/\/forums?\.somethingawful\.com\//i );
            if (samatch) {
               if ( location.href.indexOf("showthread.php?") != -1 ) {
                  reanchorThreadToLink(doc);
               }
            }
         }
         return;
      }
   }
   catch (ex) { }
}

var SALR_SilenceLoadErrors = false;
var firstLoad = true;
var loadCount = 0;

/*
 *
 *  onload Handler
 *  This function is a clusterfuck of immense proportions.
 *
 */
function salastread_windowOnLoad(e) {
   //alert("e is "+e+"\ne.originalTarget.location.href is "+e.originalTarget.location.href);
   //if ( e.originalTarget == "[Object HTMLDocument]" ) {
   //   alert("originalTarget is " + e.originalTarget + "\ntypeof = "+typeof(e.originalTarget));
   //}
   //var doc = window._content.document;
   //SALR_UpdateStatusBarIcon();
   SALR_SilenceLoadErrors = false;

   var doc = e.originalTarget;
   var location = doc.location;
   try {
      if ( location && location.href && !doc.__salastread_processed ) {
         var samatch = location.href.match( /^http:\/\/forums?\.somethingawful\.com\//i );
         if (samatch) {
            salastread_addUpdateIcon(doc);
            // Moved below, where it should be
            //if (persistObject.toggle_removeHeaderAndFooter) {
            //   salastread_hidePageHeader(doc);
            //}
         }
      }
   } catch(ex) { }

   if ( persistObject._killed==true ) {
      if ( persistObject._killMessage!="" ) {
         alert( "SA Last Read Message:\n\n" + persistObject._killMessage );
      }
      persistObject._killMessage = "";
      return;
   }

   try {
      loadCount++;
      if (firstLoad) {
         firstLoad = false;
         if ( persistObject.toggle_showSAForumMenu && persistObject.forumListXml && persistObject.forumListXml != null ) {
            try { buildSAForumMenu(); } catch(xx) { alert("buildsaforummenu err:"+xx); };
         }
         // DOMContentLoaded test...
         //__TEST__hookupTitleChanged();
         document.getElementById("appcontent").addEventListener("DOMContentLoaded", salastread_windowOnLoad, false);
         document.getElementById("contentAreaContextMenu").addEventListener("popupshowing", SALR_ContextMenuShowing, false);
      }
      if (loadCount==3) {
         if (needToShowChangeLog==true) {
            needToShowChangeLog = false;
            showChangelogWindow();
         }
         window.removeEventListener('load', salastread_windowOnLoad, true);
         window.addEventListener('load', SALR_windowOnLoadMini, true);
      }
      //var doc = e.originalTarget;
      //var location = doc.location;
      if (doc.__salastread_processed) {
         if ( persistObject.toggle_reanchorThreadOnLoad ) {
            var samatch = location.href.match( /^http:\/\/forums?\.somethingawful\.com\//i );
            if (samatch) {
               if ( location.href.indexOf("showthread.php?") != -1 ) {
                  reanchorThreadToLink(doc);
               }
            }
         }
         return;
      }
      if ( location && location.href && !doc.__salastread_processed ) {
         var samatch = location.href.match( /^http:\/\/forums?\.somethingawful\.com\//i );
         if (samatch && doc.defaultView.getComputedStyle(doc.body,'').getPropertyValue('background-color')!="rgb(255, 153, 153)") {
//            var newPageTimer = persistObject.TimeManager.GetStart();
//            doc.__SALASTREAD_PAGETIMER = newPageTimer;
//            thisWindowPageTimers.push(newPageTimer);
            // why the FUCK doesn't this work?
            //doc.addEventListener("unload", function() { alert("a"); doc.__SALASTREAD_PAGETIMER.Finalize(); }, true);
            var hresult = 0;
            if ( location.href.indexOf("forumdisplay.php?") != -1 ) {
               hresult = handleForumDisplay(e);
               addInternalDebugLog("forumdisplay.php handler");
            }
            else if ( location.href.indexOf("showthread.php?") != -1 ) {
               handleShowThread(e);
            }
            else if ( location.href.indexOf("newreply.php") != -1 ) {
               handleNewReply(e);
            }
            else if ( location.href.indexOf("editpost.php") != -1 ) {
               handleEditPost(e);
            }
            else if ( location.href.indexOf("member2.php") != -1 ||
                      location.href.indexOf("usercp.php") != -1 ) {
               handleSubscriptions(e);
            }
            else if ( location.href.indexOf("member.php") != -1 &&
                      location.href.indexOf("salr_") != -1 ) {
               SALR_HandleProfileInsertion(e);
            }
            var hcliresult = handleConfigLinkInsertion(e);
            handleBodyClassing(e);
            //salastread_addUpdateIcon(doc);
            doc.__salastread_processed = true;
            // XXX: The unload prevents FF 1.5 from using Quick Back Button.
            //      SALR needs to work with it, but this works to prevent trouble in the meantime.
            if (true) {
               var screl = doc.createElement("SCRIPT");
               screl.setAttribute("language","javascript");
               screl.setAttribute("src","chrome://salastread/content/pageunload.js");
               doc.getElementsByTagName('head')[0].appendChild(screl);
            }
            SALR_IncTimer();
            if ( persistObject.toggle_enableDebugMarkup ) {
               var dbg = doc.createElement("DIV");
               dbg.innerHTML = SALR_debugLog.join("<br>");
               doc.body.appendChild(dbg);
            }
            if ( persistObject.toggle_removePageTitlePrefix ) {
               var titlematch = doc.title.match( /^The Something Awful Forums \- (.*)$/ );
               if (titlematch) {
                  doc.title = titlematch[1] + " - The Something Awful Forums";
               }
            }
            if (persistObject.toggle_removeHeaderAndFooter) {
               salastread_hidePageHeader(doc);
            }
            if (persistObject.toggle_props) {
               var ssel = doc.createElement("LINK");
               ssel.setAttribute('rel',"STYLESHEET");
               ssel.setAttribute('type',"text/css");
               ssel.setAttribute('href',"chrome://salastread/content/props.css");
               //ssel.setAttribute('href',"file://C|/Documents%20and%20Settings/Tim%20Fries/Desktop/SALastRead/src/jar/content/salastread/props.css");
               //ssel.setAttribute('href','data:text/css,body{background:red;}');
               doc.getElementsByTagName('head')[0].appendChild(ssel);
            }
         //} else {
         //   if ( location.href == "chrome://salastread/content/configuration.html" ) {
         //      doc.persistObject = persistObject;
         //   }
         }
      }
   }
   catch(ex) {
      if ( !e.runSilent || SALR_SilenceLoadErrors ) {
         if (typeof(ex)=="object")
         {
            var errstr = "";
            for ( var tn in ex ) {
               errstr += tn+": "+ex[tn]+"\n";
            }
            if (!persistObject || !persistObject.toggle_suppressErrors)
              alert("SALastRead application err: "+errstr);
         } else {
            if (!persistObject || !persistObject.toggle_suppressErrors)
              alert("SALastRead application err: "+ex);
         }
      } else {
         throw ex;
      }
   }
//   cleanupLostPageTimers();
}

function SALR_PageUnloadHandler() {
   alert("a");
}

function SALR_ContentUpdateCurrentBrowser() {
   //window.setTimeout( function() { SALR_UpdateStatusBarIcon(); }, 10 );
}

/*
function SALR_UpdateStatusBarIcon() {
   var cont = document.getElementById("content");
   try {
      var doc = cont.mCurrentBrowser.contentDocument;
      if ( doc && doc.location && doc.location.hostname && doc.location.hostname.match(/somethingawful\.com$/i) ) {
         document.getElementById("somethingawful-button").style.display = "-moz-box";
      } else {
         document.getElementById("somethingawful-button").style.display = "none";
      }
   }
   catch (ex) {
      document.getElementById("somethingawful-button").style.display = "none";
   }
}
*/

function SALR_ShowContextMenuItem(id) {
   var cacm = document.getElementById("contentAreaContextMenu");
   var mopt = document.getElementById("salastread-context-menu");
   var moptsep = document.getElementById("salastread-context-menuseparator");
   cacm.removeChild(mopt);
   cacm.removeChild(moptsep);
   if ( persistObject.toggle_contextMenuOnBottom ) {
      cacm.appendChild(moptsep);
      cacm.appendChild(mopt);
   } else {
      cacm.insertBefore( moptsep, cacm.firstChild );
      cacm.insertBefore( mopt, moptsep );
   }
   document.getElementById(id).style.display = "-moz-box";
   mopt.style.display = "-moz-box";
   moptsep.style.display = "-moz-box";
}

function SALR_HideContextMenuItems() {
   document.getElementById("salastread-context-menu").style.display = "none";
   document.getElementById("salastread-context-menuseparator").style.display = "none";
   var pu = document.getElementById("salastread-context-menupopup");
   for (var i=0; i<pu.childNodes.length; i++) {
      pu.childNodes[i].style.display = "none";
      pu.childNodes[i].data = "";
   }
}

function SALR_ContextMenuShowing(e) {
   if ( e.originalTarget == document.getElementById("contentAreaContextMenu") ) {
      SALR_HideContextMenuItems();
      try {
         var doc = document.getElementById("content").mCurrentBrowser.contentDocument;
         if ( doc.__salastread_processed == true ) {
            SALR_ContextVis_IgnoreThisThread(doc);
            SALR_ContextVis_StarThisThread(doc);
            //SALR_ContextVis_ThreadWatch(doc);
          }
      }
      catch (ex) {
      }
   }
}

function SALR_ContextVis_IgnoreThisThread(doc) {
   var target = gContextMenu.target;
   var threadid = null;
   while (target) {
      if (target.className) {
         var tidmatch = target.className.match(/salastread_thread_(\d+)/);
         if (tidmatch) {
            threadid = tidmatch[1];
            SALR_ShowContextMenuItem("salastread-context-ignorethread");
            document.getElementById("salastread-context-ignorethread").data = threadid;
            document.getElementById("salastread-context-ignorethread").lpdtvalue = target.lpdtvalue;
            document.getElementById("salastread-context-ignorethread").target = target;
            document.getElementById("salastread-context-ignorethread").label = "Ignore This Thread ("+threadid+")";
         }
      }
      target = target.parentNode;
   }
}

function SALR_ContextVis_StarThisThread(doc) {
   var target = gContextMenu.target;
   var threadid = null;
   while (target) {
      if (target.className) {
         var tidmatch = target.className.match(/salastread_thread_(\d+)/);
         if (tidmatch) {
            threadid = tidmatch[1];
            slurpIntoThreadCache(threadid);
            SALR_ShowContextMenuItem("salastread-context-starthread");
            document.getElementById("salastread-context-starthread").data = threadid;
            document.getElementById("salastread-context-starthread").lpdtvalue = target.lpdtvalue;
            document.getElementById("salastread-context-starthread").target = target;
            if ( cachedThreadEntry && cachedThreadEntry.getAttribute("star")=="1" ) {
               document.getElementById("salastread-context-starthread").label = "Unstar This Thread ("+threadid+")";
            } else {
               document.getElementById("salastread-context-starthread").label = "Star This Thread ("+threadid+")";
            }
         }
      }
      target = target.parentNode;
   }
}

function SALR_ContextVis_ThreadWatch(doc) {
   if ( doc.location.href.indexOf("showthread.php")!=-1 ) {
      var tidmatch = doc.location.href.match(/threadid=(\d+)/);
      if (tidmatch) {
         var threadid = tidmatch[1];
         SALR_ShowContextMenuItem("salastread-context-threadwatch");
         document.getElementById("salastread-context-threadwatch").data = threadid;
         document.getElementById("salastread-context-threadwatch").label = "ThreadWatch ("+threadid+")";
      }
   }
}

function SALR_StarThread() {
   var threadid = document.getElementById("salastread-context-starthread").data;
   var lpdtvalue = document.getElementById("salastread-context-starthread").lpdtvalue;
   var target = document.getElementById("salastread-context-starthread").target;
   if (threadid) {
      slurpIntoThreadCache(threadid);
      cachedThreadEntry.setAttribute("star", (cachedThreadEntry.getAttribute("star")=="1") ? "0" : "1");
      //persistObject.SaveXML();
      var threaddetails = new Array();
      threaddetails['id'] = threadid;
      threaddetails['star'] = cachedThreadEntry.getAttribute("star");
      persistObject.SavePostDataSQL(threaddetails);
      if ( target.ownerDocument.location.href.indexOf("showthread.php")==-1 ) {
         target.ownerDocument.location = target.ownerDocument.location;
      } else {
         var startext = cachedThreadEntry.getAttribute("star")=="0" ? "unstarred" : "starred";
         alert("This thread is now "+startext+".");
      }
   }
}

function SALR_IgnoreThread() {
   var threadid = document.getElementById("salastread-context-ignorethread").data;
   var lpdtvalue = document.getElementById("salastread-context-ignorethread").lpdtvalue;
   var target = document.getElementById("salastread-context-ignorethread").target;
   if (threadid) {
      if ( confirm("Are you sure you want to ignore thread #"+threadid+"?") ) {
         slurpIntoThreadCache(threadid);
         cachedThreadEntry.setAttribute("ignore", "1");
         if ( cachedThreadEntry.getBypassAttribute("lastpostdt")==0 ) {
            cachedThreadEntry.setAttribute("lastpostdt", GetCurrentLPDateTime());
            cachedThreadEntry.setAttribute("lastpostid", "1");
         }
         //persistObject.SaveXML();
         var threaddetails = new Array();
         threaddetails['id'] = threadid;
         threaddetails['ignore'] = 1;
         threaddetails['lastpostdt'] = GetCurrentLPDateTime();
         threaddetails['lastpostid'] = 1;
         persistObject.SavePostDataSQL(threaddetails);
         target.style.display = "none";
      }
   } else {
      alert("menu item with no threadid.");
   }
}

function SALR_ThreadWatch() {
   window.open("chrome://salastread/content/threadwatch/threadwatch.xul", "_blank",
               "chrome, centerscreen, titlebar, resizable");
}

function showChangelogWindow() {
   //window.open("chrome://salastread/content/changelog.xul?autopop=1", "changelog", "chrome,centerscreen,resizable,modal");
   var param = new Object();
   param["upgradeFromVersion"] = upgradeFromVersion;
   //window.open("chrome://salastread/content/changelog.xul?autopop=1", "changelog", "chrome,centerscreen,resizable", param);
   openDialog("chrome://salastread/content/newfeatures/newfeatures.xul", "SALR_newfeatures", "chrome,centerscreen,dialog=no", param);
}

var killcheckxmlhttp;

function saLastReadKillCheck() {
   persistObject._killChecked = true;
   if ( persistObject.toggle_dontCheckKillSwitch ) {
      return;
   }
   killcheckxmlhttp = new XMLHttpRequest();
   killcheckxmlhttp.open("GET","http://static.evercrest.com/www/images2/ext/sa/salastread-kill.xml",true);
   killcheckxmlhttp.onreadystatechange = function() {
      try {
         if (killcheckxmlhttp.readyState==2) {
            if (killcheckxmlhttp.status != 200) {
               //alert("aborting ks xml");
               killcheckxmlhttp.abort();
            }
         }
         else if (killcheckxmlhttp.readyState==4) {
            //alert("processing ks xml ("+killcheckxmlhttp.responseText+")...");
            var xdoc = killcheckxmlhttp.responseXML;
            if ( xdoc!=null ) {
               var xel = xdoc.documentElement;
               if ( xel!=null ) {
                  var before = xel.getAttribute("before");
                  if ( Number(before) > 1912 ) {
                     persistObject._killed = true;
                     persistObject._killMessage = "Please upgrade to a newer version of the SA Last Read extension.\n"+
                                                  "The version you have installed is "+
                                                  "out of date and has been disabled for this browser session.";
                  }
                  for (var x=0; x<xel.childNodes.length; x++) {
                     var thischild = xel.childNodes[x];
                     if (thischild.nodeName == "dev" ) {
                        var currentver = thischild.getAttribute("current");
                        var updateurl = thischild.getAttribute("url");
                        if ( Number(currentver) > 1912 ) {
                           persistObject._updateURL = updateurl;
                        }
                     }
                  }
                  //DELETEME -- Uncomment this to force a killed version
                  //persistObject._killed = true;
                  //persistObject._killMessage = "This should never be released.";
                  return;
               }
            }
            //persistObject._killed = true;
            //persistObject._killMessage = "Failed to get kill switch XML.";
         }
      }
      catch (e) {
         //alert("SALastRead Kill Switch Check Error: "+e);
      }
   };
   killcheckxmlhttp.send(null);
}

try {
   persistObject = Components.classes["@evercrest.com/salastread/persist-object;1"]
                      .createInstance(Components.interfaces.nsISupports);
   persistObject = persistObject.wrappedJSObject;
   if (!persistObject)
      throw "Failed to create persistObject.";
   if (persistObject.SALRversion != "1.15.1912") {
      persistObject = null;
      throw "XPCOM/Overlay version mismatch. Your Firefox profile is probably corrupt. Google for \"firefox profile support\" for help in setting up a new, clean profile.";
   }
   if (!persistObject._syncTransferObject) {
      persistObject.SetSyncTransferObject(new SALR_FTPTransferObject());
   }
   var isWindows = (navigator.platform.indexOf("Win")!=-1);
   persistObject.ProfileInit(isWindows);
   if (persistObject._starterr) {
      alert( "SALR Startup Error:\n\n"+persistObject._starterr );
   }
   setInterval(SALR_TimerTick, 1000);
   setInterval(function(){SALR_SyncTick(false,false);}, 60*1000);
   setTimeout(function(){SALR_SyncTick(false,false);}, 10);
   persistObject._PNGCreator = new PNGMaker();
   if (persistObject._killChecked == false) {
      saLastReadKillCheck();
   }
   //if (persistObject._killed!=true) {
//      if ( persistObject && persistObject.TimeManager == null ) {
//         var tm = new SALastRead_TimeManager();
//         persistObject.TimeManager = tm;
//      }
      if ( persistObject && persistObject.LastRunVersion != SALR_CURRENT_VERSION ) {
         needToShowChangeLog = true;
         upgradeFromVersion = persistObject.LastRunVersion;
         persistObject.LastRunVersion = SALR_CURRENT_VERSION;
      }
      if ( typeof(persistObject.xmlDoc) != "undefined" ) {
         window.addEventListener('load', salastread_windowOnLoad, true);
         window.addEventListener('beforeunload', salastread_windowOnBeforeUnload, true);
         window.addEventListener('unload', salastread_windowOnUnload, true);
      } else {
         alert("persistObject._starterr =\n" + persistObject._starterr);
      }
   //}
}
catch (e)
{
   alert("SALastRead init error: "+e);
   if(persistObject)
      alert("persistObject._starterr =\n" + persistObject._starterr);
}

/*
setTimeout(attachUpdater, 1);

function attachUpdater() {
   document.getElementById("content").addEventListener("select", SALR_ContentUpdateCurrentBrowser, true);
}
*/
